[smali] update to 2.0 final

This commit is contained in:
Connor Tumbleson 2013-10-11 11:43:59 -05:00
parent 5fa3c2d297
commit 03fc77cca8
168 changed files with 69 additions and 28897 deletions

View File

@ -263,7 +263,7 @@ public class ClassDefinition {
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method);
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);
@ -308,7 +308,7 @@ public class ClassDefinition {
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method);
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);

View File

@ -31,6 +31,7 @@ package org.jf.baksmali.Adaptors;
import com.google.common.collect.ImmutableList;
import org.jf.baksmali.Adaptors.Debug.DebugMethodItem;
import org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory;
import org.jf.baksmali.baksmaliOptions;
import org.jf.dexlib2.AccessFlags;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
@ -113,7 +114,8 @@ public class MethodDefinition {
}
}
public static void writeEmptyMethodTo(IndentingWriter writer, Method method) throws IOException {
public static void writeEmptyMethodTo(IndentingWriter writer, Method method,
baksmaliOptions options) throws IOException {
writer.write(".method ");
writeAccessFlags(writer, method.getAccessFlags());
writer.write(method.getName());
@ -127,7 +129,7 @@ public class MethodDefinition {
writer.write('\n');
writer.indent(4);
writeParameters(writer, method, methodParameters);
writeParameters(writer, method, methodParameters, options);
AnnotationFormatter.writeTo(writer, method.getAnnotations());
writer.deindent(4);
writer.write(".end method\n");
@ -164,7 +166,7 @@ public class MethodDefinition {
writer.printSignedIntAsDec(methodImpl.getRegisterCount());
}
writer.write('\n');
writeParameters(writer, method, methodParameters);
writeParameters(writer, method, methodParameters, classDef.options);
if (registerFormatter == null) {
registerFormatter = new RegisterFormatter(classDef.options, methodImpl.getRegisterCount(),
@ -218,7 +220,8 @@ public class MethodDefinition {
}
private static void writeParameters(IndentingWriter writer, Method method,
List<? extends MethodParameter> parameters) throws IOException {
List<? extends MethodParameter> parameters,
baksmaliOptions options) throws IOException {
boolean isStatic = AccessFlags.STATIC.isSet(method.getAccessFlags());
int registerNumber = isStatic?0:1;
for (MethodParameter parameter: parameters) {
@ -229,7 +232,7 @@ public class MethodDefinition {
writer.write(".param p");
writer.printSignedIntAsDec(registerNumber);
if (parameterName != null) {
if (parameterName != null && options.outputDebugInfo) {
writer.write(", ");
ReferenceFormatter.writeStringReference(writer, parameterName);
}

View File

@ -148,7 +148,7 @@ public class main {
options.addCodeOffsets = true;
break;
case 'r':
String[] values = commandLine.getOptionValues("r");
String[] values = commandLine.getOptionValues('r');
int registerInfo = 0;
if (values == null || values.length == 0) {

View File

@ -104,7 +104,7 @@ public class AnalysisTest {
className.substring(1, className.length() - 1));
String smaliContents = readResource(smaliPath);
Assert.assertEquals(smaliContents, stringWriter.toString().replace("\r\n", "\n"));
Assert.assertEquals(smaliContents.replace("\r\n", "\n"), stringWriter.toString().replace("\r\n", "\n"));
}
}

View File

@ -31,7 +31,7 @@
apply plugin: 'idea'
version = '2.0b5'
version = '2.0'
def jarVersion = version
@ -98,4 +98,8 @@ buildscript {
dependencies {
classpath 'org.eclipse.jgit:org.eclipse.jgit:2.0.0.201206130900-r'
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.8'
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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('brut.apktool.smali:util')
compile depends.findbugs
compile depends.guava
}

View File

@ -1,610 +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.dexlib;
import com.google.common.base.Preconditions;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.util.ExceptionWithContext;
import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.ReadOnlyArrayList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
@Nullable
private AnnotationSetItem classAnnotations;
@Nullable
private FieldAnnotation[] fieldAnnotations;
@Nullable
private MethodAnnotation[] methodAnnotations;
@Nullable
private ParameterAnnotation[] parameterAnnotations;
/**
* Creates a new uninitialized <code>AnnotationDirectoryItem</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
protected AnnotationDirectoryItem(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>AnnotationDirectoryItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param classAnnotations The annotations associated with the overall class
* @param fieldAnnotations A list of <code>FieldAnnotation</code> objects that contain the field annotations for
* this class
* @param methodAnnotations A list of <code>MethodAnnotation</code> objects that contain the method annotations for
* this class
* @param parameterAnnotations A list of <code>ParameterAnnotation</code> objects that contain the parameter
* annotations for the methods in this class
*/
private AnnotationDirectoryItem(DexFile dexFile, @Nullable AnnotationSetItem classAnnotations,
@Nullable List<FieldAnnotation> fieldAnnotations,
@Nullable List<MethodAnnotation> methodAnnotations,
@Nullable List<ParameterAnnotation> parameterAnnotations) {
super(dexFile);
this.classAnnotations = classAnnotations;
if (fieldAnnotations == null || fieldAnnotations.size() == 0) {
this.fieldAnnotations = null;
} else {
this.fieldAnnotations = new FieldAnnotation[fieldAnnotations.size()];
this.fieldAnnotations = fieldAnnotations.toArray(this.fieldAnnotations);
Arrays.sort(this.fieldAnnotations);
}
if (methodAnnotations == null || methodAnnotations.size() == 0) {
this.methodAnnotations = null;
} else {
this.methodAnnotations = new MethodAnnotation[methodAnnotations.size()];
this.methodAnnotations = methodAnnotations.toArray(this.methodAnnotations);
Arrays.sort(this.methodAnnotations);
}
if (parameterAnnotations == null || parameterAnnotations.size() == 0) {
this.parameterAnnotations = null;
} else {
this.parameterAnnotations = new ParameterAnnotation[parameterAnnotations.size()];
this.parameterAnnotations = parameterAnnotations.toArray(this.parameterAnnotations);
Arrays.sort(this.parameterAnnotations);
}
}
/**
* Returns an <code>AnnotationDirectoryItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param classAnnotations The annotations associated with the class
* @param fieldAnnotations A list of <code>FieldAnnotation</code> objects containing the field annotations
* @param methodAnnotations A list of <code>MethodAnnotation</code> objects containing the method annotations
* @param parameterAnnotations A list of <code>ParameterAnnotation</code> objects containin the parameter
* annotations
* @return an <code>AnnotationItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
*/
public static AnnotationDirectoryItem internAnnotationDirectoryItem(DexFile dexFile,
AnnotationSetItem classAnnotations,
List<FieldAnnotation> fieldAnnotations,
List<MethodAnnotation> methodAnnotations,
List<ParameterAnnotation> parameterAnnotations) {
AnnotationDirectoryItem annotationDirectoryItem = new AnnotationDirectoryItem(dexFile, classAnnotations,
fieldAnnotations, methodAnnotations, parameterAnnotations);
return dexFile.AnnotationDirectoriesSection.intern(annotationDirectoryItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
classAnnotations = (AnnotationSetItem)readContext.getOptionalOffsettedItemByOffset(
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
int fieldAnnotationCount = in.readInt();
if (fieldAnnotationCount > 0) {
fieldAnnotations = new FieldAnnotation[fieldAnnotationCount];
} else {
fieldAnnotations = null;
}
int methodAnnotationCount = in.readInt();
if (methodAnnotationCount > 0) {
methodAnnotations = new MethodAnnotation[methodAnnotationCount];
} else {
methodAnnotations = null;
}
int parameterAnnotationCount = in.readInt();
if (parameterAnnotationCount > 0) {
parameterAnnotations = new ParameterAnnotation[parameterAnnotationCount];
} else {
parameterAnnotations = null;
}
if (fieldAnnotations != null) {
for (int i=0; i<fieldAnnotations.length; i++) {
try {
FieldIdItem fieldIdItem = dexFile.FieldIdsSection.getItemByIndex(in.readInt());
AnnotationSetItem fieldAnnotationSet = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
fieldAnnotations[i] = new FieldAnnotation(fieldIdItem, fieldAnnotationSet);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex,
"Error occured while reading FieldAnnotation at index " + i);
}
}
}
if (methodAnnotations != null) {
for (int i=0; i<methodAnnotations.length; i++) {
try {
MethodIdItem methodIdItem = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
AnnotationSetItem methodAnnotationSet = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
methodAnnotations[i] = new MethodAnnotation(methodIdItem, methodAnnotationSet);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex,
"Error occured while reading MethodAnnotation at index " + i);
}
}
}
if (parameterAnnotations != null) {
for (int i=0; i<parameterAnnotations.length; i++) {
try {
MethodIdItem methodIdItem = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
AnnotationSetRefList paramaterAnnotationSet = (AnnotationSetRefList)readContext.getOffsettedItemByOffset(
ItemType.TYPE_ANNOTATION_SET_REF_LIST, in.readInt());
parameterAnnotations[i] = new ParameterAnnotation(methodIdItem, paramaterAnnotationSet);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex,
"Error occured while reading ParameterAnnotation at index " + i);
}
}
}
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
return offset + 16 + (
(fieldAnnotations==null?0:fieldAnnotations.length) +
(methodAnnotations==null?0:methodAnnotations.length) +
(parameterAnnotations==null?0:parameterAnnotations.length)) * 8;
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
if (out.annotates()) {
TypeIdItem parentType = getParentType();
if (parentType != null) {
out.annotate(0, parentType.getTypeDescriptor());
}
if (classAnnotations != null) {
out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset()));
} else {
out.annotate(4, "class_annotations_off:");
}
int length = fieldAnnotations==null?0:fieldAnnotations.length;
out.annotate(4, "annotated_fields_size: 0x" + Integer.toHexString(length) + " (" +
length + ")");
length = methodAnnotations==null?0:methodAnnotations.length;
out.annotate(4, "annotated_methods_size: 0x" + Integer.toHexString(length) + " (" +
length + ")");
length = parameterAnnotations==null?0:parameterAnnotations.length;
out.annotate(4, "annotated_parameters_size: 0x" + Integer.toHexString(length) + " (" +
length + ")");
int index;
if (fieldAnnotations != null) {
index = 0;
for (FieldAnnotation fieldAnnotation: fieldAnnotations) {
out.annotate(0, "[" + index++ + "] field_annotation");
out.indent();
out.annotate(4, "field: " + fieldAnnotation.field.getFieldName().getStringValue() + ":" +
fieldAnnotation.field.getFieldType().getTypeDescriptor());
out.annotate(4, "annotations_off: 0x" +
Integer.toHexString(fieldAnnotation.annotationSet.getOffset()));
out.deindent();
}
}
if (methodAnnotations != null) {
index = 0;
for (MethodAnnotation methodAnnotation: methodAnnotations) {
out.annotate(0, "[" + index++ + "] method_annotation");
out.indent();
out.annotate(4, "method: " + methodAnnotation.method.getMethodString());
out.annotate(4, "annotations_off: 0x" +
Integer.toHexString(methodAnnotation.annotationSet.getOffset()));
out.deindent();
}
}
if (parameterAnnotations != null) {
index = 0;
for (ParameterAnnotation parameterAnnotation: parameterAnnotations) {
out.annotate(0, "[" + index++ + "] parameter_annotation");
out.indent();
out.annotate(4, "method: " + parameterAnnotation.method.getMethodString());
out.annotate(4, "annotations_off: 0x" +
Integer.toHexString(parameterAnnotation.annotationSet.getOffset()));
}
}
}
out.writeInt(classAnnotations==null?0:classAnnotations.getOffset());
out.writeInt(fieldAnnotations==null?0:fieldAnnotations.length);
out.writeInt(methodAnnotations==null?0:methodAnnotations.length);
out.writeInt(parameterAnnotations==null?0:parameterAnnotations.length);
if (fieldAnnotations != null) {
for (FieldAnnotation fieldAnnotation: fieldAnnotations) {
out.writeInt(fieldAnnotation.field.getIndex());
out.writeInt(fieldAnnotation.annotationSet.getOffset());
}
}
if (methodAnnotations != null) {
for (MethodAnnotation methodAnnotation: methodAnnotations) {
out.writeInt(methodAnnotation.method.getIndex());
out.writeInt(methodAnnotation.annotationSet.getOffset());
}
}
if (parameterAnnotations != null) {
for (ParameterAnnotation parameterAnnotation: parameterAnnotations) {
out.writeInt(parameterAnnotation.method.getIndex());
out.writeInt(parameterAnnotation.annotationSet.getOffset());
}
}
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
TypeIdItem parentType = getParentType();
if (parentType == null) {
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
}
return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) +
" (" + parentType.getTypeDescriptor() + ")";
}
/** {@inheritDoc} */
public int compareTo(AnnotationDirectoryItem o) {
Preconditions.checkNotNull(o);
TypeIdItem parentType = getParentType();
TypeIdItem otherParentType = o.getParentType();
if (parentType != null) {
if (otherParentType != null) {
return parentType.compareTo(otherParentType);
}
return 1;
}
if (otherParentType != null) {
return -1;
}
if (classAnnotations != null) {
if (o.classAnnotations != null) {
return classAnnotations.compareTo(o.classAnnotations);
}
return 1;
}
return -1;
}
/**
* Returns the parent type for an AnnotationDirectoryItem that is guaranteed to have a single parent, or null
* for one that may be referenced by multiple classes.
*
* Specifically, the AnnotationDirectoryItem may be referenced by multiple classes if it has only class annotations,
* but not field/method/parameter annotations.
*
* @return The parent type for this AnnotationDirectoryItem, or null if it may have multiple parents
*/
@Nullable
public TypeIdItem getParentType() {
if (fieldAnnotations != null && fieldAnnotations.length > 0) {
return fieldAnnotations[0].field.getContainingClass();
}
if (methodAnnotations != null && methodAnnotations.length > 0) {
return methodAnnotations[0].method.getContainingClass();
}
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
return parameterAnnotations[0].method.getContainingClass();
}
return null;
}
/**
* @return An <code>AnnotationSetItem</code> containing the annotations associated with this class, or null
* if there are no class annotations
*/
@Nullable
public AnnotationSetItem getClassAnnotations() {
return classAnnotations;
}
/**
* Get a list of the field annotations in this <code>AnnotationDirectoryItem</code>
* @return A list of FieldAnnotation objects, or null if there are no field annotations
*/
@Nonnull
public List<FieldAnnotation> getFieldAnnotations() {
if (fieldAnnotations == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(fieldAnnotations);
}
/**
* Get a list of the method annotations in this <code>AnnotationDirectoryItem</code>
* @return A list of MethodAnnotation objects, or null if there are no method annotations
*/
@Nonnull
public List<MethodAnnotation> getMethodAnnotations() {
if (methodAnnotations == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(methodAnnotations);
}
/**
* Get a list of the parameter annotations in this <code>AnnotationDirectoryItem</code>
* @return A list of ParameterAnnotation objects, or null if there are no parameter annotations
*/
@Nonnull
public List<ParameterAnnotation> getParameterAnnotations() {
if (parameterAnnotations == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(parameterAnnotations);
}
/**
* Gets the field annotations for the given field, or null if no annotations are defined for that field
* @param fieldIdItem The field to get the annotations for
* @return An <code>AnnotationSetItem</code> containing the field annotations, or null if none are found
*/
@Nullable
public AnnotationSetItem getFieldAnnotations(FieldIdItem fieldIdItem) {
if (fieldAnnotations == null) {
return null;
}
int index = Arrays.binarySearch(fieldAnnotations, fieldIdItem);
if (index < 0) {
return null;
}
return fieldAnnotations[index].annotationSet;
}
/**
* Gets the method annotations for the given method, or null if no annotations are defined for that method
* @param methodIdItem The method to get the annotations for
* @return An <code>AnnotationSetItem</code> containing the method annotations, or null if none are found
*/
@Nullable
public AnnotationSetItem getMethodAnnotations(MethodIdItem methodIdItem) {
if (methodAnnotations == null) {
return null;
}
int index = Arrays.binarySearch(methodAnnotations, methodIdItem);
if (index < 0) {
return null;
}
return methodAnnotations[index].annotationSet;
}
/**
* Gets the parameter annotations for the given method, or null if no parameter annotations are defined for that
* method
* @param methodIdItem The method to get the parameter annotations for
* @return An <code>AnnotationSetRefList</code> containing the parameter annotations, or null if none are found
*/
@Nullable
public AnnotationSetRefList getParameterAnnotations(MethodIdItem methodIdItem) {
if (parameterAnnotations == null) {
return null;
}
int index = Arrays.binarySearch(parameterAnnotations, methodIdItem);
if (index < 0) {
return null;
}
return parameterAnnotations[index].annotationSet;
}
/**
*
*/
public int getClassAnnotationCount() {
if (classAnnotations == null) {
return 0;
}
AnnotationItem[] annotations = classAnnotations.getAnnotations();
return annotations.length;
}
/**
* @return The number of field annotations in this <code>AnnotationDirectoryItem</code>
*/
public int getFieldAnnotationCount() {
if (fieldAnnotations == null) {
return 0;
}
return fieldAnnotations.length;
}
/**
* @return The number of method annotations in this <code>AnnotationDirectoryItem</code>
*/
public int getMethodAnnotationCount() {
if (methodAnnotations == null) {
return 0;
}
return methodAnnotations.length;
}
/**
* @return The number of parameter annotations in this <code>AnnotationDirectoryItem</code>
*/
public int getParameterAnnotationCount() {
if (parameterAnnotations == null) {
return 0;
}
return parameterAnnotations.length;
}
@Override
public int hashCode() {
// If the item has a single parent, we can use the re-use the identity (hash) of that parent
TypeIdItem parentType = getParentType();
if (parentType != null) {
return parentType.hashCode();
}
if (classAnnotations != null) {
return classAnnotations.hashCode();
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this==o) {
return true;
}
if (o==null || !this.getClass().equals(o.getClass())) {
return false;
}
AnnotationDirectoryItem other = (AnnotationDirectoryItem)o;
return (this.compareTo(other) == 0);
}
public static class FieldAnnotation implements Comparable<Convertible<FieldIdItem>>, Convertible<FieldIdItem> {
public final FieldIdItem field;
public final AnnotationSetItem annotationSet;
public FieldAnnotation(FieldIdItem field, AnnotationSetItem annotationSet) {
this.field = field;
this.annotationSet = annotationSet;
}
public int compareTo(Convertible<FieldIdItem> other) {
return field.compareTo(other.convert());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return compareTo((FieldAnnotation)o) == 0;
}
@Override
public int hashCode() {
return field.hashCode() + 31 * annotationSet.hashCode();
}
public FieldIdItem convert() {
return field;
}
}
public static class MethodAnnotation implements Comparable<Convertible<MethodIdItem>>, Convertible<MethodIdItem> {
public final MethodIdItem method;
public final AnnotationSetItem annotationSet;
public MethodAnnotation(MethodIdItem method, AnnotationSetItem annotationSet) {
this.method = method;
this.annotationSet = annotationSet;
}
public int compareTo(Convertible<MethodIdItem> other) {
return method.compareTo(other.convert());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return compareTo((MethodAnnotation)o) == 0;
}
@Override
public int hashCode() {
return method.hashCode() + 31 * annotationSet.hashCode();
}
public MethodIdItem convert() {
return method;
}
}
public static class ParameterAnnotation implements Comparable<Convertible<MethodIdItem>>,
Convertible<MethodIdItem> {
public final MethodIdItem method;
public final AnnotationSetRefList annotationSet;
public ParameterAnnotation(MethodIdItem method, AnnotationSetRefList annotationSet) {
this.method = method;
this.annotationSet = annotationSet;
}
public int compareTo(Convertible<MethodIdItem> other) {
return method.compareTo(other.convert());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return compareTo((ParameterAnnotation)o) == 0;
}
@Override
public int hashCode() {
return method.hashCode() + 31 * annotationSet.hashCode();
}
public MethodIdItem convert() {
return method;
}
}
}

View File

@ -1,162 +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.dexlib;
import org.jf.dexlib.EncodedValue.AnnotationEncodedSubValue;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
public class AnnotationItem extends Item<AnnotationItem> {
private int hashCode = 0;
private AnnotationVisibility visibility;
private AnnotationEncodedSubValue annotationValue;
/**
* Creates a new uninitialized <code>AnnotationItem</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
protected AnnotationItem(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>AnnotationItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param visibility The visibility of this annotation
* @param annotationValue The value of this annotation
*/
private AnnotationItem(DexFile dexFile, AnnotationVisibility visibility,
AnnotationEncodedSubValue annotationValue) {
super(dexFile);
this.visibility = visibility;
this.annotationValue = annotationValue;
}
/**
* Returns an <code>AnnotationItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param visibility The visibility of this annotation
* @param annotationValue The value of this annotation
* @return an <code>AnnotationItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
*/
public static AnnotationItem internAnnotationItem(DexFile dexFile, AnnotationVisibility visibility,
AnnotationEncodedSubValue annotationValue) {
AnnotationItem annotationItem = new AnnotationItem(dexFile, visibility, annotationValue);
return dexFile.AnnotationsSection.intern(annotationItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
visibility = AnnotationVisibility.fromByte(in.readByte());
annotationValue = new AnnotationEncodedSubValue(dexFile, in);
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
return annotationValue.placeValue(offset + 1);
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate("visibility: " + visibility.name());
out.writeByte(visibility.value);
annotationValue.writeValue(out);
}else {
out.writeByte(visibility.value);
annotationValue.writeValue(out);
}
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATION_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
return "annotation_item @0x" + Integer.toHexString(getOffset());
}
/** {@inheritDoc} */
public int compareTo(AnnotationItem o) {
int comp = visibility.value - o.visibility.value;
if (comp == 0) {
comp = annotationValue.compareTo(o.annotationValue);
}
return comp;
}
/**
* @return The visibility of this annotation
*/
public AnnotationVisibility getVisibility() {
return visibility;
}
/**
* @return The encoded annotation value of this annotation
*/
public AnnotationEncodedSubValue getEncodedAnnotation() {
return annotationValue;
}
/**
* calculate and cache the hashcode
*/
private void calcHashCode() {
hashCode = visibility.value;
hashCode = hashCode * 31 + annotationValue.hashCode();
}
@Override
public int hashCode() {
//there's a small possibility that the actual hash code will be 0. If so, we'll
//just end up recalculating it each time
if (hashCode == 0)
calcHashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (this==o) {
return true;
}
if (o==null || !this.getClass().equals(o.getClass())) {
return false;
}
AnnotationItem other = (AnnotationItem)o;
return visibility == other.visibility && annotationValue.equals(other.annotationValue);
}
}

View File

@ -1,190 +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.dexlib;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class AnnotationSetItem extends Item<AnnotationSetItem> {
private int hashCode = 0;
private AnnotationItem[] annotations;
/**
* Creates a new uninitialized <code>AnnotationSetItem</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
protected AnnotationSetItem(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>AnnotationSetItem</code> for the given annotations
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param annotations The annotations for this <code>AnnotationSetItem</code>
*/
private AnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) {
super(dexFile);
this.annotations = annotations;
}
/**
* Returns an <code>AnnotationSetItem</code> for the given annotations, and that has been interned into the given
* <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param annotations The annotations for this <code>AnnotationSetItem</code>
* @return an <code>AnnotationSetItem</code> for the given annotations
*/
public static AnnotationSetItem internAnnotationSetItem(DexFile dexFile, List<AnnotationItem> annotations) {
AnnotationSetItem annotationSetItem;
if (annotations == null) {
annotationSetItem = new AnnotationSetItem(dexFile, new AnnotationItem[0]);
} else {
AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()];
annotations.toArray(annotationsArray);
annotationSetItem = new AnnotationSetItem(dexFile, annotationsArray);
}
return dexFile.AnnotationSetsSection.intern(annotationSetItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
annotations = new AnnotationItem[in.readInt()];
for (int i=0; i<annotations.length; i++) {
annotations[i] = (AnnotationItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_ITEM,
in.readInt());
}
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
return offset + 4 + annotations.length * 4;
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
Arrays.sort(annotations, new Comparator<AnnotationItem>() {
public int compare(AnnotationItem annotationItem, AnnotationItem annotationItem2) {
int annotationItemIndex = annotationItem.getEncodedAnnotation().annotationType.getIndex();
int annotationItemIndex2 = annotationItem2.getEncodedAnnotation().annotationType.getIndex();
if (annotationItemIndex < annotationItemIndex2) {
return -1;
} else if (annotationItemIndex == annotationItemIndex2) {
return 0;
}
return 1;
}
});
if (out.annotates()) {
out.annotate(4, "size: 0x" + Integer.toHexString(annotations.length) + " (" + annotations.length + ")");
for (AnnotationItem annotationItem: annotations) {
out.annotate(4, "annotation_off: 0x" + Integer.toHexString(annotationItem.getOffset()) + " - " +
annotationItem.getEncodedAnnotation().annotationType.getTypeDescriptor());
}
}
out.writeInt(annotations.length);
for (AnnotationItem annotationItem: annotations) {
out.writeInt(annotationItem.getOffset());
}
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATION_SET_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
}
/** {@inheritDoc} */
public int compareTo(AnnotationSetItem o) {
if (o == null) {
return 1;
}
int comp = annotations.length - o.annotations.length;
if (comp == 0) {
for (int i=0; i<annotations.length; i++) {
comp = annotations[i].compareTo(o.annotations[i]);
if (comp != 0) {
return comp;
}
}
}
return comp;
}
/**
* @return An array of the <code>AnnotationItem</code> objects in this <code>AnnotationSetItem</code>
*/
public AnnotationItem[] getAnnotations() {
return annotations;
}
/**
* calculate and cache the hashcode
*/
private void calcHashCode() {
hashCode = 0;
for (AnnotationItem annotationItem: annotations) {
hashCode = hashCode * 31 + annotationItem.hashCode();
}
}
@Override
public int hashCode() {
//there's a small possibility that the actual hash code will be 0. If so, we'll
//just end up recalculating it each time
if (hashCode == 0)
calcHashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (this==o) {
return true;
}
if (o==null || !this.getClass().equals(o.getClass())) {
return false;
}
AnnotationSetItem other = (AnnotationSetItem)o;
return (this.compareTo(other) == 0);
}
}

View File

@ -1,170 +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.dexlib;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
import java.util.List;
public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
private int hashCode = 0;
private AnnotationSetItem[] annotationSets;
/**
* Creates a new uninitialized <code>AnnotationSetRefList</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
protected AnnotationSetRefList(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>AnnotationSetRefList</code> for the given annotation sets
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param annotationSets The annotationSets for this <code>AnnotationSetRefList</code>
*/
private AnnotationSetRefList(DexFile dexFile, AnnotationSetItem[] annotationSets) {
super(dexFile);
this.annotationSets = annotationSets;
}
/**
* Returns an <code>AnnotationSetRefList</code> for the given annotation sets, and that has been interned into the
* given <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param annotationSets The annotation sets for this <code>AnnotationSetRefList</code>
* @return an <code>AnnotationSetItem</code> for the given annotations
*/
public static AnnotationSetRefList internAnnotationSetRefList(DexFile dexFile,
List<AnnotationSetItem> annotationSets) {
AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()];
annotationSets.toArray(annotationSetsArray);
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray);
return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
annotationSets = new AnnotationSetItem[in.readInt()];
for (int i=0; i<annotationSets.length; i++) {
annotationSets[i] = (AnnotationSetItem)readContext.getOptionalOffsettedItemByOffset(
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
}
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
return offset + 4 + annotationSets.length * 4;
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length +
")");
for (AnnotationSetItem annotationSetItem: annotationSets) {
out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset()));
}
}
out.writeInt(annotationSets.length);
for (AnnotationSetItem annotationSetItem: annotationSets) {
out.writeInt(annotationSetItem.getOffset());
}
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_ANNOTATION_SET_REF_LIST;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
}
/** {@inheritDoc} */
public int compareTo(AnnotationSetRefList o) {
int comp = annotationSets.length - o.annotationSets.length;
if (comp != 0) {
return comp;
}
for (int i=0; i<annotationSets.length; i++) {
comp = annotationSets[i].compareTo(o.annotationSets[i]);
if (comp != 0) {
return comp;
}
}
return comp;
}
/**
* @return An array of the <code>AnnotationSetItem</code> objects that make up this
* <code>AnnotationSetRefList</code>
*/
public AnnotationSetItem[] getAnnotationSets() {
return annotationSets;
}
/**
* calculate and cache the hashcode
*/
private void calcHashCode() {
hashCode = 0;
for (AnnotationSetItem annotationSetItem: annotationSets) {
hashCode = hashCode * 31 + annotationSetItem.hashCode();
}
}
@Override
public int hashCode() {
//there's a small possibility that the actual hash code will be 0. If so, we'll
//just end up recalculating it each time
if (hashCode == 0)
calcHashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (this==o) {
return true;
}
if (o==null || !this.getClass().equals(o.getClass())) {
return false;
}
AnnotationSetRefList other = (AnnotationSetRefList)o;
return (this.compareTo(other) == 0);
}
}

View File

@ -1,55 +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.dexlib;
public enum AnnotationVisibility {
BUILD((byte)0, "build"),
RUNTIME((byte)1, "runtime"),
SYSTEM((byte)2, "system");
public final byte value;
public final String visibility;
private AnnotationVisibility(byte value, String visibility) {
this.value = value;
this.visibility = visibility;
}
public static AnnotationVisibility fromByte(byte value) {
switch (value) {
case (byte)0:
return BUILD;
case (byte)1:
return RUNTIME;
case (byte)2:
return SYSTEM;
default:
throw new RuntimeException("Invalid annotation visibility value: " + value);
}
}
}

View File

@ -1,844 +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.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;
import java.util.*;
public class ClassDataItem extends Item<ClassDataItem> {
@Nullable
private EncodedField[] staticFields = null;
@Nullable
private EncodedField[] instanceFields = null;
@Nullable
private EncodedMethod[] directMethods = null;
@Nullable
private EncodedMethod[] virtualMethods = null;
/**
* Creates a new uninitialized <code>ClassDataItem</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
public ClassDataItem(final DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>ClassDataItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param staticFields The static fields for this class
* @param instanceFields The instance fields for this class
* @param directMethods The direct methods for this class
* @param virtualMethods The virtual methods for this class
*/
private ClassDataItem(DexFile dexFile, @Nullable EncodedField[] staticFields,
@Nullable EncodedField[] instanceFields, @Nullable EncodedMethod[] directMethods,
@Nullable EncodedMethod[] virtualMethods) {
super(dexFile);
this.staticFields = staticFields;
this.instanceFields = instanceFields;
this.directMethods = directMethods;
this.virtualMethods = virtualMethods;
}
/**
* Creates a new <code>ClassDataItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param staticFields The static fields for this class
* @param instanceFields The instance fields for this class
* @param directMethods The direct methods for this class
* @param virtualMethods The virtual methods for this class
* @return a new <code>ClassDataItem</code> with the given values
*/
public static ClassDataItem internClassDataItem(DexFile dexFile, @Nullable List<EncodedField> staticFields,
@Nullable List<EncodedField> instanceFields,
@Nullable List<EncodedMethod> directMethods,
@Nullable List<EncodedMethod> virtualMethods) {
EncodedField[] staticFieldsArray = null;
EncodedField[] instanceFieldsArray = null;
EncodedMethod[] directMethodsArray = null;
EncodedMethod[] virtualMethodsArray = null;
if (staticFields != null && staticFields.size() > 0) {
SortedSet<EncodedField> staticFieldsSet = new TreeSet<EncodedField>();
for (EncodedField staticField: staticFields) {
if (staticFieldsSet.contains(staticField)) {
System.err.println(String.format("Ignoring duplicate static field definition: %s",
staticField.field.getFieldString()));
continue;
}
staticFieldsSet.add(staticField);
}
staticFieldsArray = new EncodedField[staticFieldsSet.size()];
staticFieldsArray = staticFieldsSet.toArray(staticFieldsArray);
}
if (instanceFields != null && instanceFields.size() > 0) {
SortedSet<EncodedField> instanceFieldsSet = new TreeSet<EncodedField>();
for (EncodedField instanceField: instanceFields) {
if (instanceFieldsSet.contains(instanceField)) {
System.err.println(String.format("Ignoring duplicate instance field definition: %s",
instanceField.field.getFieldString()));
continue;
}
instanceFieldsSet.add(instanceField);
}
instanceFieldsArray = new EncodedField[instanceFieldsSet.size()];
instanceFieldsArray = instanceFieldsSet.toArray(instanceFieldsArray);
}
TreeSet<EncodedMethod> directMethodSet = new TreeSet<EncodedMethod>();
if (directMethods != null && directMethods.size() > 0) {
for (EncodedMethod directMethod: directMethods) {
if (directMethodSet.contains(directMethod)) {
System.err.println(String.format("Ignoring duplicate direct method definition: %s",
directMethod.method.getMethodString()));
continue;
}
directMethodSet.add(directMethod);
}
directMethodsArray = new EncodedMethod[directMethodSet.size()];
directMethodsArray = directMethodSet.toArray(directMethodsArray);
}
if (virtualMethods != null && virtualMethods.size() > 0) {
TreeSet<EncodedMethod> virtualMethodSet = new TreeSet<EncodedMethod>();
for (EncodedMethod virtualMethod: virtualMethods) {
if (directMethodSet.contains(virtualMethod)) {
// If both a direct and virtual definition is present, dalvik's behavior seems to be undefined,
// so we can't gracefully handle this case, like we can if the duplicates are all direct or all
// virtual -- in which case, we ignore all but the first definition
throw new RuntimeException(String.format("Duplicate direct+virtual method definition: %s",
virtualMethod.method.getMethodString()));
}
if (virtualMethodSet.contains(virtualMethod)) {
System.err.println(String.format("Ignoring duplicate virtual method definition: %s",
virtualMethod.method.getMethodString()));
continue;
}
virtualMethodSet.add(virtualMethod);
}
virtualMethodsArray = new EncodedMethod[virtualMethodSet.size()];
virtualMethodsArray = virtualMethodSet.toArray(virtualMethodsArray);
}
ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFieldsArray, instanceFieldsArray,
directMethodsArray, virtualMethodsArray);
return dexFile.ClassDataSection.intern(classDataItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
int staticFieldsCount = in.readUnsignedLeb128();
int instanceFieldsCount = in.readUnsignedLeb128();
int directMethodsCount = in.readUnsignedLeb128();
int virtualMethodsCount = in.readUnsignedLeb128();
if (staticFieldsCount > 0) {
staticFields = new EncodedField[staticFieldsCount];
EncodedField previousEncodedField = null;
for (int i=0; i<staticFieldsCount; i++) {
try {
staticFields[i] = previousEncodedField = new EncodedField(dexFile, in, previousEncodedField);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex, "Error while reading static field at index " + i);
}
}
}
if (instanceFieldsCount > 0) {
instanceFields = new EncodedField[instanceFieldsCount];
EncodedField previousEncodedField = null;
for (int i=0; i<instanceFieldsCount; i++) {
try {
instanceFields[i] = previousEncodedField = new EncodedField(dexFile, in, previousEncodedField);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex, "Error while reading instance field at index " + i);
}
}
}
if (directMethodsCount > 0) {
directMethods = new EncodedMethod[directMethodsCount];
EncodedMethod previousEncodedMethod = null;
for (int i=0; i<directMethodsCount; i++) {
try {
directMethods[i] = previousEncodedMethod = new EncodedMethod(dexFile, readContext, in,
previousEncodedMethod);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex, "Error while reading direct method at index " + i);
}
}
}
if (virtualMethodsCount > 0) {
virtualMethods = new EncodedMethod[virtualMethodsCount];
EncodedMethod previousEncodedMethod = null;
for (int i=0; i<virtualMethodsCount; i++) {
try {
virtualMethods[i] = previousEncodedMethod = new EncodedMethod(dexFile, readContext, in,
previousEncodedMethod);
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex, "Error while reading virtual method at index " + i);
}
}
}
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
offset += Leb128Utils.unsignedLeb128Size(getStaticFieldCount());
offset += Leb128Utils.unsignedLeb128Size(getInstanceFieldCount());
offset += Leb128Utils.unsignedLeb128Size(getDirectMethodCount());
offset += Leb128Utils.unsignedLeb128Size(getVirtualMethodCount());
if (staticFields != null) {
EncodedField previousEncodedField = null;
for (EncodedField encodedField: staticFields) {
offset = encodedField.place(offset, previousEncodedField);
previousEncodedField = encodedField;
}
}
if (instanceFields != null) {
EncodedField previousEncodedField = null;
for (EncodedField encodedField: instanceFields) {
offset = encodedField.place(offset, previousEncodedField);
previousEncodedField = encodedField;
}
}
if (directMethods != null) {
EncodedMethod previousEncodedMethod = null;
for (EncodedMethod encodedMethod: directMethods) {
offset = encodedMethod.place(offset, previousEncodedMethod);
previousEncodedMethod = encodedMethod;
}
}
if (virtualMethods != null) {
EncodedMethod previousEncodedMethod = null;
for (EncodedMethod encodedMethod: virtualMethods) {
offset = encodedMethod.place(offset, previousEncodedMethod);
previousEncodedMethod = encodedMethod;
}
}
return offset;
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
if (out.annotates()) {
int staticFieldCount = getStaticFieldCount();
out.annotate("static_fields_size: 0x" + Integer.toHexString(staticFieldCount) + " (" +
staticFieldCount + ")");
out.writeUnsignedLeb128(staticFieldCount);
int instanceFieldCount = getInstanceFieldCount();
out.annotate("instance_fields_size: 0x" + Integer.toHexString(instanceFieldCount) + " (" +
instanceFieldCount + ")");
out.writeUnsignedLeb128(instanceFieldCount);
int directMethodCount = getDirectMethodCount();
out.annotate("direct_methods_size: 0x" + Integer.toHexString(directMethodCount) + " (" +
directMethodCount + ")");
out.writeUnsignedLeb128(directMethodCount);
int virtualMethodCount = getVirtualMethodCount();
out.annotate("virtual_methods_size: 0x" + Integer.toHexString(virtualMethodCount) + " (" +
virtualMethodCount + ")");
out.writeUnsignedLeb128(virtualMethodCount);
if (staticFields != null) {
int index = 0;
EncodedField previousEncodedField = null;
for (EncodedField encodedField: staticFields) {
out.annotate("[" + index++ + "] static_field");
out.indent();
encodedField.writeTo(out, previousEncodedField);
out.deindent();
previousEncodedField = encodedField;
}
}
if (instanceFields != null) {
int index = 0;
EncodedField previousEncodedField = null;
for (EncodedField encodedField: instanceFields) {
out.annotate("[" + index++ + "] instance_field");
out.indent();
encodedField.writeTo(out, previousEncodedField);
out.deindent();
previousEncodedField = encodedField;
}
}
if (directMethods != null) {
int index = 0;
EncodedMethod previousEncodedMethod = null;
for (EncodedMethod encodedMethod: directMethods) {
out.annotate("[" + index++ + "] direct_method");
out.indent();
encodedMethod.writeTo(out, previousEncodedMethod);
out.deindent();
previousEncodedMethod = encodedMethod;
}
}
if (virtualMethods != null) {
int index = 0;
EncodedMethod previousEncodedMethod = null;
for (EncodedMethod encodedMethod: virtualMethods) {
out.annotate("[" + index++ + "] virtual_method");
out.indent();
encodedMethod.writeTo(out, previousEncodedMethod);
out.deindent();
previousEncodedMethod = encodedMethod;
}
}
} else {
out.writeUnsignedLeb128(getStaticFieldCount());
out.writeUnsignedLeb128(getInstanceFieldCount());
out.writeUnsignedLeb128(getDirectMethodCount());
out.writeUnsignedLeb128(getVirtualMethodCount());
if (staticFields != null) {
EncodedField previousEncodedField = null;
for (EncodedField encodedField: staticFields) {
encodedField.writeTo(out, previousEncodedField);
previousEncodedField = encodedField;
}
}
if (instanceFields != null) {
EncodedField previousEncodedField = null;
for (EncodedField encodedField: instanceFields) {
encodedField.writeTo(out, previousEncodedField);
previousEncodedField = encodedField;
}
}
if (directMethods != null) {
EncodedMethod previousEncodedMethod = null;
for (EncodedMethod encodedMethod: directMethods) {
encodedMethod.writeTo(out, previousEncodedMethod);
previousEncodedMethod = encodedMethod;
}
}
if (virtualMethods != null) {
EncodedMethod previousEncodedMethod = null;
for (EncodedMethod encodedMethod: virtualMethods) {
encodedMethod.writeTo(out, previousEncodedMethod);
previousEncodedMethod = encodedMethod;
}
}
}
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_CLASS_DATA_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
TypeIdItem parentType = getParentType();
if (parentType == null) {
return "class_data_item @0x" + Integer.toHexString(getOffset());
}
return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parentType.getTypeDescriptor() +")";
}
/** {@inheritDoc} */
public int compareTo(ClassDataItem other) {
Preconditions.checkNotNull(other);
// An empty CodeDataItem may be shared by multiple ClassDefItems, so we can't use parent in this case
if (isEmpty()) {
if (other.isEmpty()) {
return 0;
}
return -1;
}
if (other.isEmpty()) {
return 1;
}
TypeIdItem parentType = getParentType();
TypeIdItem otherParentType= other.getParentType();
if (parentType == null) {
if (otherParentType == null) {
return 0;
}
return -1;
}
if (otherParentType == null) {
return 1;
}
return parentType.compareTo(otherParentType);
}
@Override
public int hashCode() {
// If the item has a single parent, we can use the re-use the identity (hash) of that parent
TypeIdItem parentType = getParentType();
if (parentType != null) {
return parentType.hashCode();
}
return 0;
}
/**
* Returns the parent type for a non-empty ClassDataItem, or null for an empty one (which could be referenced by
* multiple ClassDefItem parents)
*
* Only an empty ClassDataItem may have multiple parents.
*
* @return The parent type for this ClassDefItem, or null if it may have multiple parents
*/
@Nullable
public TypeIdItem getParentType() {
if (staticFields != null && staticFields.length > 0) {
return staticFields[0].field.getContainingClass();
}
if (instanceFields != null && instanceFields.length > 0) {
return instanceFields[0].field.getContainingClass();
}
if (directMethods != null && directMethods.length > 0) {
return directMethods[0].method.getContainingClass();
}
if (virtualMethods != null && virtualMethods.length > 0) {
return virtualMethods[0].method.getContainingClass();
}
return null;
}
/**
* @return the static fields for this class
*/
@Nonnull
public List<EncodedField> getStaticFields() {
if (staticFields == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(staticFields);
}
/**
* @return the instance fields for this class
*/
@Nonnull
public List<EncodedField> getInstanceFields() {
if (instanceFields == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(instanceFields);
}
/**
* @return the direct methods for this class
*/
@Nonnull
public List<EncodedMethod> getDirectMethods() {
if (directMethods == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(directMethods);
}
/**
* @return the virtual methods for this class
*/
@Nonnull
public List<EncodedMethod> getVirtualMethods() {
if (virtualMethods == null) {
return Collections.emptyList();
}
return ReadOnlyArrayList.of(virtualMethods);
}
/**
* @return The number of static fields in this <code>ClassDataItem</code>
*/
public int getStaticFieldCount() {
if (staticFields == null) {
return 0;
}
return staticFields.length;
}
/**
* @return The number of instance fields in this <code>ClassDataItem</code>
*/
public int getInstanceFieldCount() {
if (instanceFields == null) {
return 0;
}
return instanceFields.length;
}
/**
* @return The number of direct methods in this <code>ClassDataItem</code>
*/
public int getDirectMethodCount() {
if (directMethods == null) {
return 0;
}
return directMethods.length;
}
/**
* @return The number of virtual methods in this <code>ClassDataItem</code>
*/
public int getVirtualMethodCount() {
if (virtualMethods == null) {
return 0;
}
return virtualMethods.length;
}
/**
* @return true if this is an empty ClassDataItem
*/
public boolean isEmpty() {
return (getStaticFieldCount() + getInstanceFieldCount() +
getDirectMethodCount() + getVirtualMethodCount()) == 0;
}
/**
* Performs a binary search for the definition of the specified direct method
* @param methodIdItem The MethodIdItem of the direct method to search for
* @return The EncodedMethod for the specified direct method, or null if not found
*/
public EncodedMethod findDirectMethodByMethodId(MethodIdItem methodIdItem) {
return findMethodByMethodIdInternal(methodIdItem.index, directMethods);
}
/**
* Performs a binary search for the definition of the specified virtual method
* @param methodIdItem The MethodIdItem of the virtual method to search for
* @return The EncodedMethod for the specified virtual method, or null if not found
*/
public EncodedMethod findVirtualMethodByMethodId(MethodIdItem methodIdItem) {
return findMethodByMethodIdInternal(methodIdItem.index, virtualMethods);
}
/**
* Performs a binary search for the definition of the specified method. It can be either direct or virtual
* @param methodIdItem The MethodIdItem of the virtual method to search for
* @return The EncodedMethod for the specified virtual method, or null if not found
*/
public EncodedMethod findMethodByMethodId(MethodIdItem methodIdItem) {
EncodedMethod encodedMethod = findMethodByMethodIdInternal(methodIdItem.index, directMethods);
if (encodedMethod != null) {
return encodedMethod;
}
return findMethodByMethodIdInternal(methodIdItem.index, virtualMethods);
}
private static EncodedMethod findMethodByMethodIdInternal(int methodIdItemIndex, EncodedMethod[] encodedMethods) {
int min = 0;
int max = encodedMethods.length;
while (min<max) {
int index = (min+max)>>1;
EncodedMethod encodedMethod = encodedMethods[index];
int encodedMethodIndex = encodedMethod.method.getIndex();
if (encodedMethodIndex == methodIdItemIndex) {
return encodedMethod;
} else if (encodedMethodIndex < methodIdItemIndex) {
if (min == index) {
break;
}
min = index;
} else {
if (max == index) {
break;
}
max = index;
}
}
return null;
}
public static class EncodedField implements Comparable<EncodedField> {
/**
* The <code>FieldIdItem</code> that this <code>EncodedField</code> is associated with
*/
public final FieldIdItem field;
/**
* The access flags for this field
*/
public final int accessFlags;
/**
* Constructs a new <code>EncodedField</code> with the given values
* @param field The <code>FieldIdItem</code> that this <code>EncodedField</code> is associated with
* @param accessFlags The access flags for this field
*/
public EncodedField(FieldIdItem field, int accessFlags) {
this.field = field;
this.accessFlags = accessFlags;
}
/**
* This is used internally to construct a new <code>EncodedField</code> while reading in a <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that is being read in
* @param in the Input object to read the <code>EncodedField</code> from
* @param previousEncodedField The previous <code>EncodedField</code> in the list containing this
* <code>EncodedField</code>.
*/
private EncodedField(DexFile dexFile, Input in, @Nullable EncodedField previousEncodedField) {
int previousIndex = previousEncodedField==null?0:previousEncodedField.field.getIndex();
field = dexFile.FieldIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex);
accessFlags = in.readUnsignedLeb128();
}
/**
* Writes the <code>EncodedField</code> to the given <code>AnnotatedOutput</code> object
* @param out the <code>AnnotatedOutput</code> object to write to
* @param previousEncodedField The previous <code>EncodedField</code> in the list containing this
* <code>EncodedField</code>.
*/
private void writeTo(AnnotatedOutput out, EncodedField previousEncodedField) {
int previousIndex = previousEncodedField==null?0:previousEncodedField.field.getIndex();
if (out.annotates()) {
out.annotate("field: " + field.getFieldString());
out.writeUnsignedLeb128(field.getIndex() - previousIndex);
out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForField(accessFlags));
out.writeUnsignedLeb128(accessFlags);
}else {
out.writeUnsignedLeb128(field.getIndex() - previousIndex);
out.writeUnsignedLeb128(accessFlags);
}
}
/**
* Calculates the size of this <code>EncodedField</code> and returns the offset
* immediately following it
* @param offset the offset of this <code>EncodedField</code> in the <code>DexFile</code>
* @param previousEncodedField The previous <code>EncodedField</code> in the list containing this
* <code>EncodedField</code>.
* @return the offset immediately following this <code>EncodedField</code>
*/
private int place(int offset, EncodedField previousEncodedField) {
int previousIndex = previousEncodedField==null?0:previousEncodedField.field.getIndex();
offset += Leb128Utils.unsignedLeb128Size(field.getIndex() - previousIndex);
offset += Leb128Utils.unsignedLeb128Size(accessFlags);
return offset;
}
/**
* Compares this <code>EncodedField</code> to another, based on the comparison of the associated
* <code>FieldIdItem</code>
* @param other The <code>EncodedField</code> to compare against
* @return a standard integer comparison value indicating the relationship
*/
public int compareTo(EncodedField other)
{
return field.compareTo(other.field);
}
/**
* Determines if this <code>EncodedField</code> is equal to other, based on the equality of the associated
* <code>FieldIdItem</code>
* @param other The <code>EncodedField</code> to test for equality
* @return true if other is equal to this instance, otherwise false
*/
public boolean equals(Object other) {
if (other instanceof EncodedField) {
return compareTo((EncodedField)other) == 0;
}
return false;
}
/**
* @return true if this is a static field
*/
public boolean isStatic() {
return (accessFlags & AccessFlags.STATIC.getValue()) != 0;
}
}
public static class EncodedMethod implements Comparable<EncodedMethod> {
/**
* The <code>MethodIdItem</code> that this <code>EncodedMethod</code> is associated with
*/
public final MethodIdItem method;
/**
* The access flags for this method
*/
public final int accessFlags;
/**
* The <code>CodeItem</code> containing the code for this method, or null if there is no code for this method
* (i.e. an abstract method)
*/
public final CodeItem codeItem;
/**
* Constructs a new <code>EncodedMethod</code> with the given values
* @param method The <code>MethodIdItem</code> that this <code>EncodedMethod</code> is associated with
* @param accessFlags The access flags for this method
* @param codeItem The <code>CodeItem</code> containing the code for this method, or null if there is no code
* for this method (i.e. an abstract method)
*/
public EncodedMethod(MethodIdItem method, int accessFlags, CodeItem codeItem) {
this.method = method;
this.accessFlags = accessFlags;
this.codeItem = codeItem;
if (codeItem != null) {
codeItem.setParent(this);
}
}
/**
* This is used internally to construct a new <code>EncodedMethod</code> while reading in a <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that is being read in
* @param readContext a <code>ReadContext</code> object to hold information that is only needed while reading
* in a file
* @param in the Input object to read the <code>EncodedMethod</code> from
* @param previousEncodedMethod The previous <code>EncodedMethod</code> in the list containing this
* <code>EncodedMethod</code>.
*/
public EncodedMethod(DexFile dexFile, ReadContext readContext, Input in, EncodedMethod previousEncodedMethod) {
int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex();
method = dexFile.MethodIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex);
accessFlags = in.readUnsignedLeb128();
if (dexFile.skipInstructions()) {
in.readUnsignedLeb128();
codeItem = null;
} else {
codeItem = (CodeItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CODE_ITEM,
in.readUnsignedLeb128());
}
if (codeItem != null) {
codeItem.setParent(this);
}
}
/**
* Writes the <code>EncodedMethod</code> to the given <code>AnnotatedOutput</code> object
* @param out the <code>AnnotatedOutput</code> object to write to
* @param previousEncodedMethod The previous <code>EncodedMethod</code> in the list containing this
* <code>EncodedMethod</code>.
*/
private void writeTo(AnnotatedOutput out, EncodedMethod previousEncodedMethod) {
int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex();
if (out.annotates()) {
out.annotate("method: " + method.getMethodString());
out.writeUnsignedLeb128(method.getIndex() - previousIndex);
out.annotate("access_flags: " + AccessFlags.formatAccessFlagsForMethod(accessFlags));
out.writeUnsignedLeb128(accessFlags);
if (codeItem != null) {
out.annotate("code_off: 0x" + Integer.toHexString(codeItem.getOffset()));
out.writeUnsignedLeb128(codeItem.getOffset());
} else {
out.annotate("code_off: 0x0");
out.writeUnsignedLeb128(0);
}
}else {
out.writeUnsignedLeb128(method.getIndex() - previousIndex);
out.writeUnsignedLeb128(accessFlags);
out.writeUnsignedLeb128(codeItem==null?0:codeItem.getOffset());
}
}
/**
* Calculates the size of this <code>EncodedMethod</code> and returns the offset
* immediately following it
* @param offset the offset of this <code>EncodedMethod</code> in the <code>DexFile</code>
* @param previousEncodedMethod The previous <code>EncodedMethod</code> in the list containing this
* <code>EncodedMethod</code>.
* @return the offset immediately following this <code>EncodedField</code>
*/
private int place(int offset, EncodedMethod previousEncodedMethod) {
int previousIndex = previousEncodedMethod==null?0:previousEncodedMethod.method.getIndex();
offset += Leb128Utils.unsignedLeb128Size(method.getIndex() - previousIndex);
offset += Leb128Utils.unsignedLeb128Size(accessFlags);
offset += codeItem==null?1:Leb128Utils.unsignedLeb128Size(codeItem.getOffset());
return offset;
}
/**
* Compares this <code>EncodedMethod</code> to another, based on the comparison of the associated
* <code>MethodIdItem</code>
* @param other The <code>EncodedMethod</code> to compare against
* @return a standard integer comparison value indicating the relationship
*/
public int compareTo(EncodedMethod other) {
return method.compareTo(other.method);
}
/**
* Determines if this <code>EncodedMethod</code> is equal to other, based on the equality of the associated
* <code>MethodIdItem</code>
* @param other The <code>EncodedMethod</code> to test for equality
* @return true if other is equal to this instance, otherwise false
*/
public boolean equals(Object other) {
if (other instanceof EncodedMethod) {
return compareTo((EncodedMethod)other) == 0;
}
return false;
}
/**
* @return true if this is a direct method
*/
public boolean isDirect() {
return ((accessFlags & (AccessFlags.STATIC.getValue() | AccessFlags.PRIVATE.getValue() |
AccessFlags.CONSTRUCTOR.getValue())) != 0);
}
}
}

View File

@ -1,374 +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.dexlib;
import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
import org.jf.dexlib.EncodedValue.EncodedValue;
import org.jf.dexlib.Util.AccessFlags;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.TypeUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public class ClassDefItem extends Item<ClassDefItem> {
private TypeIdItem classType;
private int accessFlags;
private @Nullable TypeIdItem superType;
private @Nullable TypeListItem implementedInterfaces;
private @Nullable StringIdItem sourceFile;
private @Nullable AnnotationDirectoryItem annotations;
private @Nullable ClassDataItem classData;
private @Nullable EncodedArrayItem staticFieldInitializers;
/**
* Creates a new uninitialized <code>ClassDefItem</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
protected ClassDefItem(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>ClassDefItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param classType The type of this class
* @param accessFlags The access flags of this class
* @param superType The superclass of this class, or null if none (only valid for java.lang.Object)
* @param implementedInterfaces A list of the interfaces that this class implements, or null if none
* @param sourceFile The main source file that this class is defined in, or null if not available
* @param annotations The annotations for this class and its fields, methods and method parameters, or null if none
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class
* @param staticFieldInitializers The initial values for this class's static fields, or null if none. The initial
* values should be in the same order as the static fields in the <code>ClassDataItem</code>. It can contain
* fewer items than static fields, in which case the remaining static fields will be initialized with a default
* value of null/0. The initial value for any fields that don't specifically have a value can be either the
* type-appropriate null/0 encoded value, or null.
*/
private ClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags, @Nullable TypeIdItem superType,
@Nullable TypeListItem implementedInterfaces, @Nullable StringIdItem sourceFile,
@Nullable AnnotationDirectoryItem annotations, @Nullable ClassDataItem classData,
@Nullable EncodedArrayItem staticFieldInitializers) {
super(dexFile);
assert classType != null;
this.classType = classType;
this.accessFlags = accessFlags;
this.superType = superType;
this.implementedInterfaces = implementedInterfaces;
this.sourceFile = sourceFile;
this.annotations = annotations;
this.classData = classData;
this.staticFieldInitializers = staticFieldInitializers;
}
/**
* Returns a <code>ClassDefItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param classType The type of this class
* @param accessFlags The access flags of this class
* @param superType The superclass of this class, or null if none (only valid for java.lang.Object)
* @param implementedInterfaces A list of the interfaces that this class implements, or null if none
* @param sourceFile The main source file that this class is defined in, or null if not available
* @param annotations The annotations for this class and its fields, methods and method parameters, or null if none
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class
* @param staticFieldInitializers The initial values for this class's static fields, or null if none. If it is not
* null, it must contain the same number of items as the number of static fields in this class. The value in the
* <code>StaticFieldInitializer</code> for any field that doesn't have an explicit initial value can either be null
* or be the type-appropriate null/0 value.
* @return a <code>ClassDefItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
*/
public static ClassDefItem internClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags,
@Nullable TypeIdItem superType, @Nullable TypeListItem implementedInterfaces,
@Nullable StringIdItem sourceFile, @Nullable AnnotationDirectoryItem annotations,
@Nullable ClassDataItem classData,
@Nullable List<StaticFieldInitializer> staticFieldInitializers) {
EncodedArrayItem encodedArrayItem = null;
if(!dexFile.getInplace() && staticFieldInitializers != null && staticFieldInitializers.size() > 0) {
assert classData != null;
assert staticFieldInitializers.size() == classData.getStaticFieldCount();
encodedArrayItem = makeStaticFieldInitializersItem(dexFile, staticFieldInitializers);
}
ClassDefItem classDefItem = new ClassDefItem(dexFile, classType, accessFlags, superType, implementedInterfaces,
sourceFile, annotations, classData, encodedArrayItem);
return dexFile.ClassDefsSection.intern(classDefItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
classType = dexFile.TypeIdsSection.getItemByIndex(in.readInt());
accessFlags = in.readInt();
superType = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readInt());
implementedInterfaces = (TypeListItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST,
in.readInt());
sourceFile = dexFile.StringIdsSection.getOptionalItemByIndex(in.readInt());
annotations = (AnnotationDirectoryItem)readContext.getOptionalOffsettedItemByOffset(
ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, in.readInt());
classData = (ClassDataItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
staticFieldInitializers = (EncodedArrayItem)readContext.getOptionalOffsettedItemByOffset(
ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
return offset + 32;
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate(4, "class_type: " + classType.getTypeDescriptor());
out.annotate(4, "access_flags: " + AccessFlags.formatAccessFlagsForClass(accessFlags));
out.annotate(4, "superclass_type: " + (superType==null?"":superType.getTypeDescriptor()));
out.annotate(4, "interfaces: " +
(implementedInterfaces==null?"":implementedInterfaces.getTypeListString(" ")));
out.annotate(4, "source_file: " + (sourceFile==null?"":sourceFile.getStringValue()));
out.annotate(4, "annotations_off: " +
(annotations==null?"":"0x"+Integer.toHexString(annotations.getOffset())));
out.annotate(4, "class_data_off:" +
(classData==null?"":"0x"+Integer.toHexString(classData.getOffset())));
out.annotate(4, "static_values_off: " +
(staticFieldInitializers==null?"":"0x"+Integer.toHexString(staticFieldInitializers.getOffset())));
}
out.writeInt(classType.getIndex());
out.writeInt(accessFlags);
out.writeInt(superType==null?-1:superType.getIndex());
out.writeInt(implementedInterfaces==null?0:implementedInterfaces.getOffset());
out.writeInt(sourceFile==null?-1:sourceFile.getIndex());
out.writeInt(annotations==null?0:annotations.getOffset());
out.writeInt(classData==null?0:classData.getOffset());
out.writeInt(staticFieldInitializers==null?0:staticFieldInitializers.getOffset());
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_CLASS_DEF_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
return "class_def_item: " + classType.getTypeDescriptor();
}
/** {@inheritDoc} */
public int compareTo(ClassDefItem o) {
//The actual sorting for this class is done during the placement phase, in ClassDefPlacer.
//This method is just used for sorting the associated ClassDataItem items after the ClassDefItems have been
//placed, so we can just do the comparison based on the offsets
return this.getOffset() - o.getOffset();
}
public TypeIdItem getClassType() {
return classType;
}
public int getAccessFlags() {
return accessFlags;
}
@Nullable
public TypeIdItem getSuperclass() {
return superType;
}
@Nullable
public TypeListItem getInterfaces() {
return implementedInterfaces;
}
@Nullable
public StringIdItem getSourceFile() {
return sourceFile;
}
@Nullable
public AnnotationDirectoryItem getAnnotations() {
return annotations;
}
@Nullable
public ClassDataItem getClassData() {
return classData;
}
@Nullable
public EncodedArrayItem getStaticFieldInitializers() {
return staticFieldInitializers;
}
public static int placeClassDefItems(IndexedSection<ClassDefItem> section, int offset) {
ClassDefPlacer cdp = new ClassDefPlacer(section);
return cdp.placeSection(offset);
}
/**
* This class places the items within a ClassDefItem section, such that superclasses and interfaces are
* placed before sub/implementing classes
*/
private static class ClassDefPlacer {
private final IndexedSection<ClassDefItem> section;
private final HashMap<TypeIdItem, ClassDefItem> unplacedClassDefsByType =
new HashMap<TypeIdItem, ClassDefItem>();
private int currentIndex = 0;
private int currentOffset;
public ClassDefPlacer(IndexedSection<ClassDefItem> section) {
this.section = section;
for (ClassDefItem classDefItem: section.items) {
TypeIdItem typeIdItem = classDefItem.classType;
unplacedClassDefsByType.put(typeIdItem, classDefItem);
}
}
public int placeSection(int offset) {
currentOffset = offset;
if (section.DexFile.getSortAllItems()) {
//presort the list, to guarantee a unique ordering
Collections.sort(section.items, new Comparator<ClassDefItem>() {
public int compare(ClassDefItem a, ClassDefItem b) {
return a.getClassType().compareTo(b.getClassType());
}
});
}
//we need to initialize the offset for all the classes to -1, so we can tell which ones
//have been placed
for (ClassDefItem classDefItem: section.items) {
classDefItem.offset = -1;
}
for (ClassDefItem classDefItem: section.items) {
placeClass(classDefItem);
}
for (ClassDefItem classDefItem: unplacedClassDefsByType.values()) {
section.items.set(classDefItem.getIndex(), classDefItem);
}
return currentOffset;
}
private void placeClass(ClassDefItem classDefItem) {
if (!classDefItem.isPlaced()) {
TypeIdItem superType = classDefItem.superType;
ClassDefItem superClassDefItem = unplacedClassDefsByType.get(superType);
if (superClassDefItem != null) {
placeClass(superClassDefItem);
}
TypeListItem interfaces = classDefItem.implementedInterfaces;
if (interfaces != null) {
for (TypeIdItem interfaceType: interfaces.getTypes()) {
ClassDefItem interfaceClass = unplacedClassDefsByType.get(interfaceType);
if (interfaceClass != null) {
placeClass(interfaceClass);
}
}
}
currentOffset = classDefItem.placeAt(currentOffset, currentIndex++);
unplacedClassDefsByType.remove(classDefItem.classType);
}
}
}
public static class StaticFieldInitializer implements Comparable<StaticFieldInitializer> {
public final EncodedValue value;
public final ClassDataItem.EncodedField field;
public StaticFieldInitializer(EncodedValue value, ClassDataItem.EncodedField field) {
this.value = value;
this.field = field;
}
public int compareTo(StaticFieldInitializer other) {
return field.compareTo(other.field);
}
}
/**
* A helper method to sort the static field initializers and populate the default values as needed
* @param dexFile the <code>DexFile</code>
* @param staticFieldInitializers the initial values
* @return an interned EncodedArrayItem containing the static field initializers
*/
private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
@Nonnull List<StaticFieldInitializer> staticFieldInitializers) {
if (staticFieldInitializers.size() == 0) {
return null;
}
int len = staticFieldInitializers.size();
// make a copy before sorting. we don't want to modify the list passed to us
staticFieldInitializers = new ArrayList<StaticFieldInitializer>(staticFieldInitializers);
Collections.sort(staticFieldInitializers);
int lastIndex = -1;
for (int i=len-1; i>=0; i--) {
StaticFieldInitializer staticFieldInitializer = staticFieldInitializers.get(i);
if (staticFieldInitializer.value != null &&
(staticFieldInitializer.value.compareTo(TypeUtils.makeDefaultValueForType(
staticFieldInitializer.field.field.getFieldType())) != 0)) {
lastIndex = i;
break;
}
}
//we don't have any non-null/non-default values, so we don't need to create an EncodedArrayItem
if (lastIndex == -1) {
return null;
}
EncodedValue[] values = new EncodedValue[lastIndex+1];
for (int i=0; i<=lastIndex; i++) {
StaticFieldInitializer staticFieldInitializer = staticFieldInitializers.get(i);
EncodedValue encodedValue = staticFieldInitializer.value;
if (encodedValue == null) {
encodedValue = TypeUtils.makeDefaultValueForType(staticFieldInitializer.field.field.getFieldType());
}
values[i] = encodedValue;
}
ArrayEncodedSubValue encodedArrayValue = new ArrayEncodedSubValue(values);
return EncodedArrayItem.internEncodedArrayItem(dexFile, encodedArrayValue);
}
}

View File

@ -1,343 +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.dexlib.Code.Analysis;
import org.jf.dexlib.Code.*;
import org.jf.dexlib.Item;
import org.jf.dexlib.ItemType;
import org.jf.dexlib.MethodIdItem;
import org.jf.util.ExceptionWithContext;
import java.util.*;
public class AnalyzedInstruction implements Comparable<AnalyzedInstruction> {
/**
* 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<AnalyzedInstruction> predecessors = new TreeSet<AnalyzedInstruction>();
/**
* Instructions that can execution could pass on to next during normal execution
*/
protected final LinkedList<AnalyzedInstruction> successors = new LinkedList<AnalyzedInstruction>();
/**
* 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;
/**
* An analyzed instruction's "deadness" is set during analysis (i.e. MethodAnalyzer.analyzer()). A dead instruction
* is one that the analyzer never reaches. This occurs either with natural "dead code" - code that simply has no
* code path that can ever reach it, or code that follows an odexed instruction that can't be deodexed.
*/
protected boolean dead = false;
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.Category.Unknown, null);
for (int i=0; i<registerCount; i++) {
preRegisterMap[i] = unknown;
postRegisterMap[i] = unknown;
}
}
public int getInstructionIndex() {
return instructionIndex;
}
public int getPredecessorCount() {
return predecessors.size();
}
public SortedSet<AnalyzedInstruction> 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.opcode.odexOnly();
this.instruction = instruction;
}
protected void restoreOdexedInstruction() {
assert originalInstruction.opcode.odexOnly();
instruction = originalInstruction;
}
public int getSuccessorCount() {
return successors.size();
}
public List<AnalyzedInstruction> getSuccesors() {
return Collections.unmodifiableList(successors);
}
public Instruction getInstruction() {
return instruction;
}
public Instruction getOriginalInstruction() {
return originalInstruction;
}
public boolean isDead() {
return dead;
}
/**
* 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 == 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 == registerType) {
return false;
}
postRegisterMap[registerNumber] = registerType;
return true;
}
protected boolean isInvokeInit() {
if (instruction == null || !instruction.opcode.canInitializeReference()) {
return false;
}
//TODO: check access flags instead of name?
InstructionWithReference instruction = (InstructionWithReference)this.instruction;
Item item = instruction.getReferencedItem();
assert item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM;
MethodIdItem method = (MethodIdItem)item;
if (!method.getMethodName().getStringValue().equals("<init>")) {
return false;
}
return true;
}
public boolean setsRegister() {
return instruction.opcode.setsRegister();
}
public boolean setsWideRegister() {
return instruction.opcode.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 <init> method is called. So even though invoke
//instructions don't normally change any registers, calling an <init> 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).getRegisterD();
} else {
assert instruction instanceof RegisterRangeInstruction;
RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction)instruction;
assert rangeInstruction.getRegCount() > 0;
destinationRegister = rangeInstruction.getStartRegister();
}
if (registerNumber == destinationRegister) {
return true;
}
RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(registerNumber);
if (preInstructionDestRegisterType.category != RegisterType.Category.UninitRef &&
preInstructionDestRegisterType.category != RegisterType.Category.UninitThis) {
return false;
}
//check if the uninit ref has been copied to another register
if (getPreInstructionRegisterType(registerNumber) == 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.opcode.setsRegister()) {
throw new ExceptionWithContext("Cannot call getDestinationRegister() for an instruction that doesn't " +
"store a value");
}
return ((SingleRegisterInstruction)instruction).getRegisterA();
}
public int getRegisterCount() {
return postRegisterMap.length;
}
public RegisterType getPostInstructionRegisterType(int registerNumber) {
return postRegisterMap[registerNumber];
}
public RegisterType getPreInstructionRegisterType(int registerNumber) {
return preRegisterMap[registerNumber];
}
public int compareTo(AnalyzedInstruction analyzedInstruction) {
//TODO: out of curiosity, check the disassembly of this to see if it retrieves the value of analyzedInstruction.instructionIndex for every access. It should, because the field is final. What about if we set the field to non-final?
if (instructionIndex < analyzedInstruction.instructionIndex) {
return -1;
} else if (instructionIndex == analyzedInstruction.instructionIndex) {
return 0;
} else {
return 1;
}
}
}

View File

@ -1,115 +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.Analysis;
import org.jf.dexlib.Code.OdexedInvokeInline;
import org.jf.dexlib.Code.OdexedInvokeVirtual;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomInlineMethodResolver extends InlineMethodResolver {
private DeodexUtil.InlineMethod[] inlineMethods;
public CustomInlineMethodResolver(String inlineTable) {
FileReader fr = null;
try {
fr = new FileReader(inlineTable);
} catch (FileNotFoundException ex) {
throw new RuntimeException("Could not find inline table file: " + inlineTable);
}
List<String> lines = new ArrayList<String>();
BufferedReader br = new BufferedReader(fr);
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 reading file: " + inlineTable, ex);
}
inlineMethods = new DeodexUtil.InlineMethod[lines.size()];
for (int i=0; i<inlineMethods.length; i++) {
inlineMethods[i] = parseAndResolveInlineMethod(lines.get(i));
}
}
@Override
public DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction analyzedInstruction) {
assert analyzedInstruction.instruction instanceof OdexedInvokeInline;
OdexedInvokeInline instruction = (OdexedInvokeInline)analyzedInstruction.instruction;
int methodIndex = instruction.getInlineIndex();
if (methodIndex < 0 || methodIndex >= inlineMethods.length) {
throw new RuntimeException("Invalid method index: " + methodIndex);
}
return inlineMethods[methodIndex];
}
private static final Pattern longMethodPattern = Pattern.compile("(L[^;]+;)->([^(]+)\\(([^)]*)\\)(.+)");
private DeodexUtil.InlineMethod parseAndResolveInlineMethod(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);
String methodParams = m.group(3);
String methodRet = m.group(4);
ClassPath.ClassDef classDef = ClassPath.getClassDef(className, false);
int methodType = classDef.getMethodType(String.format("%s(%s)%s", methodName, methodParams, methodRet));
if (methodType == -1) {
throw new RuntimeException("Cannot resolve inline method: " + inlineMethod);
}
return new DeodexUtil.InlineMethod(methodType, className, methodName, methodParams, methodRet);
}
}

View File

@ -1,293 +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.dexlib.Code.Analysis;
import org.jf.dexlib.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DeodexUtil {
public static final int Virtual = 0;
public static final int Direct = 1;
public static final int Static = 2;
private final InlineMethodResolver inlineMethodResolver;
public final DexFile dexFile;
public DeodexUtil(DexFile dexFile) {
this.dexFile = dexFile;
OdexHeader odexHeader = dexFile.getOdexHeader();
if (odexHeader == null) {
//if there isn't an odex header, why are we creating an DeodexUtil object?
assert false;
throw new RuntimeException("Cannot create a DeodexUtil object for a dex file without an odex header");
}
inlineMethodResolver = InlineMethodResolver.createInlineMethodResolver(this, odexHeader.version);
}
public DeodexUtil(DexFile dexFile, InlineMethodResolver inlineMethodResolver) {
this.dexFile = dexFile;
this.inlineMethodResolver = inlineMethodResolver;
}
public InlineMethod lookupInlineMethod(AnalyzedInstruction instruction) {
return inlineMethodResolver.resolveExecuteInline(instruction);
}
public FieldIdItem lookupField(ClassPath.ClassDef classDef, int fieldOffset) {
ClassPath.FieldDef field = classDef.getInstanceField(fieldOffset);
if (field == null) {
return null;
}
return parseAndResolveField(classDef, field);
}
private static final Pattern shortMethodPattern = Pattern.compile("([^(]+)\\(([^)]*)\\)(.+)");
public MethodIdItem lookupVirtualMethod(ClassPath.ClassDef classDef, int methodIndex) {
String method = classDef.getVirtualMethod(methodIndex);
if (method == null) {
return null;
}
Matcher m = shortMethodPattern.matcher(method);
if (!m.matches()) {
assert false;
throw new RuntimeException("Invalid method descriptor: " + method);
}
String methodName = m.group(1);
String methodParams = m.group(2);
String methodRet = m.group(3);
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.
classDef = ClassPath.getClassDef("Ljava/lang/Object;");
} else if (classDef.isInterface()) {
classDef = classDef.getSuperclass();
assert classDef != null;
}
return parseAndResolveMethod(classDef, methodName, methodParams, methodRet);
}
private MethodIdItem parseAndResolveMethod(ClassPath.ClassDef classDef, String methodName, String methodParams,
String methodRet) {
StringIdItem methodNameItem = StringIdItem.lookupStringIdItem(dexFile, methodName);
if (methodNameItem == null) {
return null;
}
LinkedList<TypeIdItem> paramList = new LinkedList<TypeIdItem>();
for (int i=0; i<methodParams.length(); i++) {
TypeIdItem typeIdItem;
switch (methodParams.charAt(i)) {
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
case 'J':
case 'F':
case 'D':
typeIdItem = TypeIdItem.lookupTypeIdItem(dexFile, methodParams.substring(i,i+1));
break;
case 'L':
{
int end = methodParams.indexOf(';', i);
if (end == -1) {
throw new RuntimeException("invalid parameter in the method");
}
typeIdItem = TypeIdItem.lookupTypeIdItem(dexFile, methodParams.substring(i, end+1));
i = end;
break;
}
case '[':
{
int end;
int typeStart = i+1;
while (typeStart < methodParams.length() && methodParams.charAt(typeStart) == '[') {
typeStart++;
}
switch (methodParams.charAt(typeStart)) {
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
case 'J':
case 'F':
case 'D':
end = typeStart;
break;
case 'L':
end = methodParams.indexOf(';', typeStart);
if (end == -1) {
throw new RuntimeException("invalid parameter in the method");
}
break;
default:
throw new RuntimeException("invalid parameter in the method");
}
typeIdItem = TypeIdItem.lookupTypeIdItem(dexFile, methodParams.substring(i, end+1));
i = end;
break;
}
default:
throw new RuntimeException("invalid parameter in the method");
}
if (typeIdItem == null) {
return null;
}
paramList.add(typeIdItem);
}
TypeListItem paramListItem = null;
if (paramList.size() > 0) {
paramListItem = TypeListItem.lookupTypeListItem(dexFile, paramList);
if (paramListItem == null) {
return null;
}
}
TypeIdItem retType = TypeIdItem.lookupTypeIdItem(dexFile, methodRet);
if (retType == null) {
return null;
}
ProtoIdItem protoItem = ProtoIdItem.lookupProtoIdItem(dexFile, retType, paramListItem);
if (protoItem == null) {
return null;
}
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) {
return methodIdItem;
}
}
methodClassDef = methodClassDef.getSuperclass();
} while (methodClassDef != null);
return null;
}
private FieldIdItem parseAndResolveField(ClassPath.ClassDef classDef, ClassPath.FieldDef field) {
String definingClass = field.definingClass;
String fieldName = field.name;
String fieldType = field.type;
StringIdItem fieldNameItem = StringIdItem.lookupStringIdItem(dexFile, fieldName);
if (fieldNameItem == null) {
return null;
}
TypeIdItem fieldTypeItem = TypeIdItem.lookupTypeIdItem(dexFile, fieldType);
if (fieldTypeItem == null) {
return null;
}
ClassPath.ClassDef fieldClass = classDef;
ArrayList<ClassPath.ClassDef> parents = new ArrayList<ClassPath.ClassDef>();
parents.add(fieldClass);
while (fieldClass != null && !fieldClass.getClassType().equals(definingClass)) {
fieldClass = fieldClass.getSuperclass();
parents.add(fieldClass);
}
for (int i=parents.size()-1; i>=0; i--) {
fieldClass = parents.get(i);
TypeIdItem classTypeItem = TypeIdItem.lookupTypeIdItem(dexFile, fieldClass.getClassType());
if (classTypeItem == null) {
continue;
}
FieldIdItem fieldIdItem = FieldIdItem.lookupFieldIdItem(dexFile, classTypeItem, fieldTypeItem, fieldNameItem);
if (fieldIdItem != null) {
return fieldIdItem;
}
}
return null;
}
public static class InlineMethod {
public final int methodType;
public final String classType;
public final String methodName;
public final String parameters;
public final String returnType;
private MethodIdItem methodIdItem = null;
InlineMethod(int methodType, String classType, String methodName, String parameters,
String returnType) {
this.methodType = methodType;
this.classType = classType;
this.methodName = methodName;
this.parameters = parameters;
this.returnType = returnType;
}
public MethodIdItem getMethodIdItem(DeodexUtil deodexUtil) {
if (methodIdItem == null) {
loadMethod(deodexUtil);
}
return methodIdItem;
}
private void loadMethod(DeodexUtil deodexUtil) {
ClassPath.ClassDef classDef = ClassPath.getClassDef(classType);
this.methodIdItem = deodexUtil.parseAndResolveMethod(classDef, methodName, parameters, returnType);
}
public String getMethodString() {
return String.format("%s->%s(%s)%s", classType, methodName, parameters, returnType);
}
}
}

View File

@ -1,56 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2011 Ben Gruver
* 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.dexlib.Code.Analysis;
import org.jf.dexlib.ClassDefItem;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.TypeIdItem;
import java.util.HashMap;
/**
* Keeps a simple map of classes defined in a dex file, allowing you to look them up by TypeIdItem or name
*/
public class DexFileClassMap {
private final HashMap<String, ClassDefItem> definedClasses = new HashMap<String, ClassDefItem>();
public DexFileClassMap(DexFile dexFile) {
for (ClassDefItem classDefItem: dexFile.ClassDefsSection.getItems()) {
definedClasses.put(classDefItem.getClassType().getTypeDescriptor(), classDefItem);
}
}
public ClassDefItem getClassDefByName(String typeName) {
return definedClasses.get(typeName);
}
public ClassDefItem getClassDefByType(TypeIdItem typeIdItem) {
return definedClasses.get(typeIdItem.getTypeDescriptor());
}
}

View File

@ -1,160 +0,0 @@
/*
* 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<String> bootClassPathDirs = Lists.newArrayList();
String outFile = "fields.txt";
for (int i=0; i<parsedOptions.length; i++) {
Option option = parsedOptions[i];
String opt = option.getOpt();
switch (opt.charAt(0)) {
case 'd':
bootClassPathDirs.add(option.getValue());
break;
case 'o':
outFile = option.getValue();
break;
default:
assert false;
}
}
if (remainingArgs.length != 1) {
usage();
return;
}
String inputDexFileName = remainingArgs[0];
File dexFileFile = new File(inputDexFileName);
if (!dexFileFile.exists()) {
System.err.println("Can't find the file " + inputDexFileName);
System.exit(1);
}
try {
DexFile dexFile = new DexFile(dexFileFile);
String[] bootClassPaths = new String[bootClassPathDirs.size()];
int j = 0;
for (String bootClassPathDir: bootClassPathDirs) {
bootClassPaths[j++] = bootClassPathDir;
}
ClassPath.InitializeClassPathFromOdex(bootClassPaths, null, inputDexFileName, dexFile, false);
FileOutputStream outStream = new FileOutputStream(outFile);
for (ClassDefItem classDefItem: dexFile.ClassDefsSection.getItems()) {
ClassPath.ClassDef classDef = ClassPath.getClassDef(classDefItem.getClassType());
SparseArray<ClassPath.FieldDef> fields = classDef.getInstanceFields();
String className = "Class " + classDef.getClassType() + " : " + fields.size() + " instance fields\n";
outStream.write(className.getBytes());
for (int i=0;i<fields.size();i++) {
String field = fields.keyAt(i) + ":" + fields.valueAt(i).type + " " + fields.valueAt(i).name + "\n";
outStream.write(field.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.DumpFields -d path/to/jar/files <dex-file>");
}
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);
}
}

View File

@ -1,159 +0,0 @@
/*
* 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<String> bootClassPathDirs = Lists.newArrayList();
String outFile = "vtables.txt";
for (int i=0; i<parsedOptions.length; i++) {
Option option = parsedOptions[i];
String opt = option.getOpt();
switch (opt.charAt(0)) {
case 'd':
bootClassPathDirs.add(option.getValue());
break;
case 'o':
outFile = option.getValue();
break;
default:
assert false;
}
}
if (remainingArgs.length != 1) {
usage();
return;
}
String inputDexFileName = remainingArgs[0];
File dexFileFile = new File(inputDexFileName);
if (!dexFileFile.exists()) {
System.err.println("Can't find the file " + inputDexFileName);
System.exit(1);
}
try {
DexFile dexFile = new DexFile(dexFileFile);
String[] bootClassPaths = new String[bootClassPathDirs.size()];
int j = 0;
for (String bootClassPathDir: bootClassPathDirs) {
bootClassPaths[j++] = bootClassPathDir;
}
ClassPath.InitializeClassPathFromOdex(bootClassPaths, null, inputDexFileName, dexFile, false);
FileOutputStream outStream = new FileOutputStream(outFile);
for (ClassDefItem classDefItem: dexFile.ClassDefsSection.getItems()) {
ClassPath.ClassDef classDef = ClassPath.getClassDef(classDefItem.getClassType());
ClassPath.VirtualMethod[] methods = classDef.getVtable();
String className = "Class " + classDef.getClassType() + " extends " + classDef.getSuperclass().getClassType() + " : " + methods.length + " methods\n";
outStream.write(className.getBytes());
for (int i=0;i<methods.length;i++) {
String method = i + ":" + methods[i].containingClass + "->" + 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 <dex-file>");
}
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);
}
}

View File

@ -1,187 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver
* 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.dexlib.Code.Analysis;
import org.jf.dexlib.Code.OdexedInvokeInline;
import org.jf.dexlib.Code.OdexedInvokeVirtual;
import static org.jf.dexlib.Code.Analysis.DeodexUtil.Static;
import static org.jf.dexlib.Code.Analysis.DeodexUtil.Virtual;
import static org.jf.dexlib.Code.Analysis.DeodexUtil.Direct;
public abstract class InlineMethodResolver {
public static InlineMethodResolver createInlineMethodResolver(DeodexUtil deodexUtil, int odexVersion) {
if (odexVersion == 35) {
return new InlineMethodResolver_version35(deodexUtil);
} else if (odexVersion == 36) {
return new InlineMethodResolver_version36(deodexUtil);
} else {
throw new RuntimeException(String.format("odex version %d is not supported yet", odexVersion));
}
}
protected InlineMethodResolver() {
}
public abstract DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction instruction);
private static class InlineMethodResolver_version35 extends InlineMethodResolver
{
private final DeodexUtil.InlineMethod[] inlineMethods;
public InlineMethodResolver_version35(DeodexUtil deodexUtil) {
inlineMethods = new DeodexUtil.InlineMethod[] {
new DeodexUtil.InlineMethod(Static, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"),
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "charAt", "I", "C"),
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"),
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"),
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "length", "", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "I", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "J", "J"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "F", "F"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "min", "II", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "max", "II", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sqrt", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "cos", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sin", "D", "D")
};
}
@Override
public DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction analyzedInstruction) {
assert analyzedInstruction.instruction instanceof OdexedInvokeInline;
OdexedInvokeInline instruction = (OdexedInvokeInline)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 DeodexUtil.InlineMethod[] inlineMethods;
private final DeodexUtil.InlineMethod indexOfIMethod;
private final DeodexUtil.InlineMethod indexOfIIMethod;
private final DeodexUtil.InlineMethod fastIndexOfMethod;
private final DeodexUtil.InlineMethod isEmptyMethod;
public InlineMethodResolver_version36(DeodexUtil deodexUtil) {
//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 = new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "I", "I");
indexOfIIMethod = new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "II", "I");
//gingerbread
fastIndexOfMethod = new DeodexUtil.InlineMethod(Direct, "Ljava/lang/String;", "fastIndexOf", "II", "I");
isEmptyMethod = new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "isEmpty", "", "Z");
inlineMethods = new DeodexUtil.InlineMethod[] {
new DeodexUtil.InlineMethod(Static, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"),
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "charAt", "I", "C"),
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"),
new DeodexUtil.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,
new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "length", "", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "I", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "J", "J"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "F", "F"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "min", "II", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "max", "II", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sqrt", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "cos", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sin", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "floatToIntBits", "F", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "floatToRawIntBits", "F", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "intBitsToFloat", "I", "F"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "doubleToLongBits", "D", "J"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "doubleToRawLongBits", "D", "J"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "longBitsToDouble", "J", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "I", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "J", "J"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "F", "F"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "D", "D"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "min", "II", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "max", "II", "I"),
new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "sqrt", "D", "D"),
};
}
@Override
public DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction analyzedInstruction) {
assert analyzedInstruction.instruction instanceof OdexedInvokeInline;
OdexedInvokeInline instruction = (OdexedInvokeInline)analyzedInstruction.instruction;
int inlineIndex = instruction.getInlineIndex();
if (inlineIndex < 0 || inlineIndex >= inlineMethods.length) {
throw new RuntimeException("Invalid method index: " + inlineIndex);
}
if (inlineIndex == 4) {
int parameterCount = getParameterCount(instruction);
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 = getParameterCount(instruction);
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];
}
private int getParameterCount(OdexedInvokeInline instruction) {
return instruction.getRegCount();
}
}
}

View File

@ -1,235 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver
* 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.dexlib.Code.Analysis;
import org.jf.dexlib.Code.Opcode;
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(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));
}
static Opcode getAndCheckDeodexedOpcodeForOdexedOpcode(String fieldType, 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 ValidationException(String.format("Incorrect field type \"%s\" for %s", fieldType,
odexedOpcode.name));
}
return deodexedOpcode;
}
}

View File

@ -1,322 +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.dexlib.Code.Analysis;
import org.jf.dexlib.TypeIdItem;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import static org.jf.dexlib.Code.Analysis.ClassPath.ClassDef;
public class RegisterType {
private final static HashMap<RegisterType, RegisterType> internedRegisterTypes =
new HashMap<RegisterType, RegisterType>();
public final Category category;
public final ClassDef type;
private RegisterType(Category category, ClassDef type) {
assert ((category == Category.Reference || category == Category.UninitRef || category == Category.UninitThis) &&
type != null) ||
((category != Category.Reference && category != Category.UninitRef && category != Category.UninitThis) &&
type == null);
this.category = category;
this.type = type;
}
@Override
public String toString() {
return "(" + category.name() + (type==null?"":("," + type.getClassType())) + ")";
}
public void writeTo(Writer writer) throws IOException {
writer.write('(');
writer.write(category.name());
if (type != null) {
writer.write(',');
writer.write(type.getClassType());
}
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;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
return true;
}
@Override
public int hashCode() {
int result = category.hashCode();
result = 31 * result + (type != null ? type.hashCode() : 0);
return result;
}
public static enum Category {
//the Unknown category denotes a register type that hasn't been determined yet
Unknown,
Uninit,
Null,
One,
Boolean,
Byte,
PosByte,
Short,
PosShort,
Char,
Integer,
Float,
LongLo,
LongHi,
DoubleLo,
DoubleHi,
//the UninitRef category is used after a new-instance operation, and before the corresponding <init> is called
UninitRef,
//the UninitThis category is used the "this" register inside an <init> method, before the superclass' <init>
//method is called
UninitThis,
Reference,
//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 incomming 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.
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 Category[][] mergeTable =
{
/* Unknown Uninit Null One, Boolean Byte PosByte Short PosShort Char Integer, Float, LongLo LongHi DoubleLo DoubleHi UninitRef UninitThis Reference Conflicted*/
/*Unknown*/ {Unknown, Uninit, Null, One, Boolean, Byte, PosByte, Short, PosShort, Char, Integer, Float, LongLo, LongHi, DoubleLo, DoubleHi, UninitRef, UninitThis, 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, PosByte, Short, PosShort, Char, Integer, Float, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Reference, Conflicted},
/*One*/ {One, Conflicted, Boolean, One, Boolean, Byte, PosByte, Short, PosShort, Char, Integer, Float, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted},
/*Boolean*/ {Boolean, Conflicted, Boolean, Boolean, Boolean, Byte, PosByte, Short, PosShort, 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},
/*PosByte*/ {PosByte, Conflicted, PosByte, PosByte, PosByte, Byte, PosByte, Short, PosShort, 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},
/*PosShort*/ {PosShort, Conflicted, PosShort, PosShort, PosShort, Short, PosShort, Short, PosShort, 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},
/*LongLo*/ {LongLo, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, LongLo, Conflicted, LongLo, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted},
/*LongHi*/ {LongHi, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, LongHi, Conflicted, LongHi, Conflicted, Conflicted, Conflicted, Conflicted},
/*DoubleLo*/ {DoubleLo, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, LongLo, Conflicted, DoubleLo, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted},
/*DoubleHi*/ {DoubleHi, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, LongHi, Conflicted, DoubleHi, Conflicted, Conflicted, Conflicted, Conflicted},
/*UninitRef*/ {UninitRef, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted},
/*UninitThis*/ {UninitThis, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, Conflicted, UninitThis, 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}
};
//this table is used to denote whether a given value type can be assigned to a "slot" of a certain type. For
//example, to determine if you can assign a Boolean value to a particular array "slot", where the array is an
//array of Integers, you would look up assignmentTable[Boolean.ordinal()][Integer.ordinal()]
//Note that not all slot types in the table are expected to be used. For example, it doesn't make sense to
//check if a value can be assigned to an uninitialized reference slot - because there is no such thing.
protected static boolean[][] assigmentTable =
{
/* Unknown Uninit Null One, Boolean Byte PosByte Short PosShort Char Integer, Float, LongLo LongHi DoubleLo DoubleHi UninitRef UninitThis Reference Conflicted |slot type*/
/*Unknown*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
/*Uninit*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
/*Null*/ {false, false, true, false, true, true, true, true, true, true, true, true, false, false, false, false, false, false, true, false},
/*One*/ {false, false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false},
/*Boolean*/ {false, false, false, false, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false},
/*Byte*/ {false, false, false, false, false, true, false, true, true, false, true, true, false, false, false, false, false, false, false, false},
/*PosByte*/ {false, false, false, false, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false},
/*Short*/ {false, false, false, false, false, false, false, true, false, false, true, true, false, false, false, false, false, false, false, false},
/*PosShort*/ {false, false, false, false, false, false, false, true, true, true, true, true, false, false, false, false, false, false, false, false},
/*Char*/ {false, false, false, false, false, false, false, false, false, true, true, true, false, false, false, false, false, false, false, false},
/*Integer*/ {false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false},
/*Float*/ {false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false},
/*LongLo*/ {false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false},
/*LongHi*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false},
/*DoubleLo*/ {false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false},
/*DoubleHi*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false},
/*UninitRef*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
/*UninitThis*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
/*Reference*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false},
/*Conflicted*/ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}
/*----------*/
/*value type*/
};
}
public static RegisterType getRegisterTypeForType(String type) {
switch (type.charAt(0)) {
case 'V':
throw new ValidationException("The V type can only be used as a method return type");
case 'Z':
return getRegisterType(Category.Boolean, null);
case 'B':
return getRegisterType(Category.Byte, null);
case 'S':
return getRegisterType(Category.Short, null);
case 'C':
return getRegisterType(Category.Char, null);
case 'I':
return getRegisterType(Category.Integer, null);
case 'F':
return getRegisterType(Category.Float, null);
case 'J':
return getRegisterType(Category.LongLo, null);
case 'D':
return getRegisterType(Category.DoubleLo, null);
case 'L':
case '[':
return getRegisterType(Category.Reference, ClassPath.getClassDef(type));
default:
throw new RuntimeException("Invalid type: " + type);
}
}
public static RegisterType getRegisterTypeForTypeIdItem(TypeIdItem typeIdItem) {
return getRegisterTypeForType(typeIdItem.getTypeDescriptor());
}
public static RegisterType getWideRegisterTypeForTypeIdItem(TypeIdItem typeIdItem, boolean firstRegister) {
if (typeIdItem.getRegisterCount() == 1) {
throw new RuntimeException("Cannot use this method for non-wide register type: " +
typeIdItem.getTypeDescriptor());
}
switch (typeIdItem.getTypeDescriptor().charAt(0)) {
case 'J':
if (firstRegister) {
return getRegisterType(Category.LongLo, null);
} else {
return getRegisterType(Category.LongHi, null);
}
case 'D':
if (firstRegister) {
return getRegisterType(Category.DoubleLo, null);
} else {
return getRegisterType(Category.DoubleHi, null);
}
default:
throw new RuntimeException("Invalid type: " + typeIdItem.getTypeDescriptor());
}
}
public static RegisterType getRegisterTypeForLiteral(long literalValue) {
if (literalValue < -32768) {
return getRegisterType(Category.Integer, null);
}
if (literalValue < -128) {
return getRegisterType(Category.Short, null);
}
if (literalValue < 0) {
return getRegisterType(Category.Byte, null);
}
if (literalValue == 0) {
return getRegisterType(Category.Null, null);
}
if (literalValue == 1) {
return getRegisterType(Category.One, null);
}
if (literalValue < 128) {
return getRegisterType(Category.PosByte, null);
}
if (literalValue < 32768) {
return getRegisterType(Category.PosShort, null);
}
if (literalValue < 65536) {
return getRegisterType(Category.Char, null);
}
return getRegisterType(Category.Integer, null);
}
public RegisterType merge(RegisterType type) {
if (type == null || type == this) {
return this;
}
Category mergedCategory = Category.mergeTable[this.category.ordinal()][type.category.ordinal()];
ClassDef mergedType = null;
if (mergedCategory == Category.Reference) {
if (this.type instanceof ClassPath.UnresolvedClassDef ||
type.type instanceof ClassPath.UnresolvedClassDef) {
mergedType = ClassPath.getUnresolvedObjectClassDef();
} else {
mergedType = ClassPath.getCommonSuperclass(this.type, type.type);
}
} else if (mergedCategory == Category.UninitRef || mergedCategory == Category.UninitThis) {
if (this.category == Category.Unknown) {
return type;
}
assert type.category == Category.Unknown;
return this;
}
return RegisterType.getRegisterType(mergedCategory, mergedType);
}
public boolean canBeAssignedTo(RegisterType slotType) {
if (Category.assigmentTable[this.category.ordinal()][slotType.category.ordinal()]) {
if (this.category == Category.Reference && slotType.category == Category.Reference) {
if (!slotType.type.isInterface()) {
return this.type.extendsClass(slotType.type);
}
//for verification, we assume all objects implement all interfaces, so we don't verify the type if
//slotType is an interface
}
return true;
}
return false;
}
public static RegisterType getUnitializedReference(ClassDef classType) {
//We always create a new RegisterType instance for an uninit ref. Each unique uninit RegisterType instance
//is used to track a specific uninitialized reference, so that if multiple registers contain the same
//uninitialized reference, then they can all be upgraded to an initialized reference when the appropriate
//<init> is invoked
return new RegisterType(Category.UninitRef, classType);
}
public static RegisterType getRegisterType(Category category, ClassDef classType) {
RegisterType newRegisterType = new RegisterType(category, classType);
RegisterType internedRegisterType = internedRegisterTypes.get(newRegisterType);
if (internedRegisterType == null) {
internedRegisterTypes.put(newRegisterType, newRegisterType);
return newRegisterType;
}
return internedRegisterType;
}
}

View File

@ -1,140 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2011 Ben Gruver
* 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.dexlib.Code.Analysis;
import org.jf.dexlib.*;
import org.jf.dexlib.Code.Format.Instruction22c;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.InstructionWithReference;
import org.jf.dexlib.Util.AccessFlags;
import java.util.HashMap;
public class SyntheticAccessorResolver {
public static final int METHOD = 0;
public static final int GETTER = 1;
public static final int SETTER = 2;
private final DexFileClassMap classMap;
private final HashMap<MethodIdItem, AccessedMember> resolvedAccessors = new HashMap<MethodIdItem, AccessedMember>();
public SyntheticAccessorResolver(DexFile dexFile) {
classMap = new DexFileClassMap(dexFile);
}
public static boolean looksLikeSyntheticAccessor(MethodIdItem methodIdItem) {
return methodIdItem.getMethodName().getStringValue().startsWith("access$");
}
public AccessedMember getAccessedMember(MethodIdItem methodIdItem) {
AccessedMember accessedMember = resolvedAccessors.get(methodIdItem);
if (accessedMember != null) {
return accessedMember;
}
ClassDefItem classDefItem = classMap.getClassDefByType(methodIdItem.getContainingClass());
if (classDefItem == null) {
return null;
}
ClassDataItem classDataItem = classDefItem.getClassData();
if (classDataItem == null) {
return null;
}
ClassDataItem.EncodedMethod encodedMethod = classDataItem.findDirectMethodByMethodId(methodIdItem);
if (encodedMethod == null) {
return null;
}
//A synthetic accessor will be marked synthetic
if ((encodedMethod.accessFlags & AccessFlags.SYNTHETIC.getValue()) == 0) {
return null;
}
Instruction[] instructions = encodedMethod.codeItem.getInstructions();
//TODO: add support for odexed formats
switch (instructions[0].opcode.format) {
case Format35c:
case Format3rc: {
//a synthetic method access should be either 2 or 3 instructions, depending on if the method returns
//anything or not
if (instructions.length < 2 || instructions.length > 3) {
return null;
}
InstructionWithReference instruction = (InstructionWithReference)instructions[0];
Item referencedItem = instruction.getReferencedItem();
if (!(referencedItem instanceof MethodIdItem)) {
return null;
}
MethodIdItem referencedMethodIdItem = (MethodIdItem)referencedItem;
accessedMember = new AccessedMember(METHOD, referencedMethodIdItem);
resolvedAccessors.put(methodIdItem, accessedMember);
return accessedMember;
}
case Format22c: {
//a synthetic field access should be exactly 2 instructions. The set/put, and then the return
if (instructions.length != 2) {
return null;
}
Instruction22c instruction = (Instruction22c)instructions[0];
Item referencedItem = instruction.getReferencedItem();
if (!(referencedItem instanceof FieldIdItem)) {
return null;
}
FieldIdItem referencedFieldIdItem = (FieldIdItem)referencedItem;
if (instruction.opcode.setsRegister() || instruction.opcode.setsWideRegister()) {
//If the instruction sets a register, that means it is a getter - it gets the field value and
//stores it in the register
accessedMember = new AccessedMember(GETTER, referencedFieldIdItem);
} else {
accessedMember = new AccessedMember(SETTER, referencedFieldIdItem);
}
resolvedAccessors.put(methodIdItem, accessedMember);
return accessedMember;
}
default:
return null;
}
}
public static class AccessedMember {
public final int accessedMemberType;
public final Item accessedMember;
public AccessedMember(int accessedMemberType, Item accessedMember) {
this.accessedMemberType = accessedMemberType;
this.accessedMember = accessedMember;
}
}
}

View File

@ -1,52 +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.dexlib.Code.Analysis;
import org.jf.util.ExceptionWithContext;
public class ValidationException extends ExceptionWithContext {
private int codeAddress;
public ValidationException(int codeAddress, String errorMessage) {
super(errorMessage);
this.codeAddress = codeAddress;
}
public ValidationException(String errorMessage) {
super(errorMessage);
}
public void setCodeAddress(int codeAddress) {
this.codeAddress = codeAddress;
}
public int getCodeAddress() {
return codeAddress;
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR 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;
public interface EncodedLiteralInstruction extends LiteralInstruction {
long getDecodedLiteral();
}

View File

@ -1,37 +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.dexlib.Code;
public interface FiveRegisterInstruction extends InvokeInstruction {
byte getRegisterA();
byte getRegisterD();
byte getRegisterE();
byte getRegisterF();
byte getRegisterG();
}

View File

@ -1,152 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
import java.util.Iterator;
public class ArrayDataPseudoInstruction extends Instruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private int elementWidth;
private byte[] encodedValues;
@Override
public int getSize(int codeAddress) {
return ((encodedValues.length + 1)/2) + 4 + (codeAddress % 2);
}
public ArrayDataPseudoInstruction(int elementWidth, byte[] encodedValues) {
super(Opcode.NOP);
if (encodedValues.length % elementWidth != 0) {
throw new RuntimeException("There are not a whole number of " + elementWidth + " byte elements");
}
this.elementWidth = elementWidth;
this.encodedValues = encodedValues;
}
public ArrayDataPseudoInstruction(byte[] buffer, int bufferIndex) {
super(Opcode.NOP);
byte opcodeByte = buffer[bufferIndex];
if (opcodeByte != 0x00) {
throw new RuntimeException("Invalid opcode byte for an ArrayData pseudo-instruction");
}
byte subopcodeByte = buffer[bufferIndex+1];
if (subopcodeByte != 0x03) {
throw new RuntimeException("Invalid sub-opcode byte for an ArrayData pseudo-instruction");
}
this.elementWidth = NumberUtils.decodeUnsignedShort(buffer, bufferIndex+2);
int elementCount = NumberUtils.decodeInt(buffer, bufferIndex+4);
this.encodedValues = new byte[elementCount * elementWidth];
System.arraycopy(buffer, bufferIndex+8, encodedValues, 0, elementCount * elementWidth);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.alignTo(4);
int elementCount = encodedValues.length / elementWidth;
out.writeByte(0x00);
out.writeByte(0x03);
out.writeShort(elementWidth);
out.writeInt(elementCount);
out.write(encodedValues);
//make sure we're written out an even number of bytes
out.alignTo(2);
}
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
"fill-array-data instruction");
}
public Format getFormat() {
return Format.ArrayData;
}
public int getElementWidth() {
return elementWidth;
}
public int getElementCount() {
return encodedValues.length / elementWidth;
}
public static class ArrayElement {
public final byte[] buffer;
public int bufferIndex;
public final int elementWidth;
public ArrayElement(byte[] buffer, int elementWidth) {
this.buffer = buffer;
this.elementWidth = elementWidth;
}
}
public Iterator<ArrayElement> getElements() {
return new Iterator<ArrayElement>() {
final int elementCount = getElementCount();
int i=0;
int position=0;
final ArrayElement arrayElement = new ArrayElement(encodedValues, getElementWidth());
public boolean hasNext() {
return i<elementCount;
}
public ArrayElement next() {
arrayElement.bufferIndex = position;
position += arrayElement.elementWidth;
i++;
return arrayElement;
}
public void remove() {
}
};
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
if (opcode != Opcode.NOP) {
throw new RuntimeException("The opcode for an ArrayDataPseudoInstruction must be NOP");
}
return new ArrayDataPseudoInstruction(buffer, bufferIndex);
}
}
}

View File

@ -1,83 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
public enum Format {
Format10t(Instruction10t.Factory, 2),
Format10x(Instruction10x.Factory, 2),
Format11n(Instruction11n.Factory, 2),
Format11x(Instruction11x.Factory, 2),
Format12x(Instruction12x.Factory, 2),
Format20bc(Instruction20bc.Factory, 4),
Format20t(Instruction20t.Factory, 4),
Format21c(Instruction21c.Factory, 4),
Format21h(Instruction21h.Factory, 4),
Format21s(Instruction21s.Factory, 4),
Format21t(Instruction21t.Factory, 4),
Format22b(Instruction22b.Factory, 4),
Format22c(Instruction22c.Factory, 4),
Format22cs(Instruction22cs.Factory, 4),
Format22s(Instruction22s.Factory, 4),
Format22t(Instruction22t.Factory, 4),
Format22x(Instruction22x.Factory, 4),
Format23x(Instruction23x.Factory, 4),
Format30t(Instruction30t.Factory, 6),
Format31c(Instruction31c.Factory, 6),
Format31i(Instruction31i.Factory, 6),
Format31t(Instruction31t.Factory, 6),
Format32x(Instruction32x.Factory, 6),
Format35c(Instruction35c.Factory, 6),
Format35mi(Instruction35mi.Factory, 6),
Format35ms(Instruction35ms.Factory, 6),
Format3rc(Instruction3rc.Factory, 6),
Format3rmi(Instruction3rmi.Factory, 6),
Format3rms(Instruction3rms.Factory, 6),
Format51l(Instruction51l.Factory, 10),
ArrayData(null, -1, true),
PackedSwitchData(null, -1, true),
SparseSwitchData(null, -1, true),
UnresolvedOdexInstruction(null, -1, false),
;
public final Instruction.InstructionFactory Factory;
public final int size;
public final boolean variableSizeFormat;
private Format(Instruction.InstructionFactory factory, int size) {
this(factory, size, false);
}
private Format(Instruction.InstructionFactory factory, int size, boolean variableSizeFormat) {
this.Factory = factory;
this.size = size;
this.variableSizeFormat = variableSizeFormat;
}
}

View File

@ -1,92 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction10t extends OffsetInstruction {
public static final InstructionFactory Factory = new Factory();
private int targetAddressOffset;
public Instruction10t(Opcode opcode, int offA) {
super(opcode);
this.targetAddressOffset = offA;
if (targetAddressOffset == 0) {
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead.");
}
//allow out of range address offsets here, so we have the option of replacing this instruction
//with goto/16 or goto/32 later
}
private Instruction10t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
assert buffer[bufferIndex] == opcode.value;
this.targetAddressOffset = buffer[bufferIndex + 1];
assert targetAddressOffset != 0;
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if (targetAddressOffset == 0) {
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead");
}
if (targetAddressOffset < -128 || targetAddressOffset > 127) {
throw new RuntimeException("The address offset is out of range. It must be in [-128,-1] or [1, 127]");
}
out.writeByte(opcode.value);
out.writeByte(targetAddressOffset);
}
public void updateTargetAddressOffset(int targetAddressOffset) {
this.targetAddressOffset = targetAddressOffset;
}
public Format getFormat() {
return Format.Format10t;
}
public int getTargetAddressOffset() {
return targetAddressOffset;
}
private static class Factory implements InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction10t(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,64 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction10x extends Instruction {
public static final InstructionFactory Factory = new Factory();
public Instruction10x(Opcode opcode) {
super(opcode);
}
public Instruction10x(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
assert (buffer[bufferIndex] & 0xFF) == opcode.value;
assert buffer[bufferIndex + 1] == 0x00;
}
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(0);
}
public Format getFormat() {
return Format.Format10x;
}
private static class Factory implements InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction10x(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,89 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.LiteralInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction11n extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
public static final InstructionFactory Factory = new Factory();
private byte regA;
private byte litB;
public Instruction11n(Opcode opcode, byte regA, byte litB) {
super(opcode);
if (regA >= 1 << 4) {
throw new RuntimeException("The register number must be less than v16");
}
if (litB < -(1 << 3) ||
litB >= 1 << 3) {
throw new RuntimeException("The literal value must be between -8 and 7 inclusive");
}
this.regA = regA;
this.litB = litB;
}
private Instruction11n(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.litB = NumberUtils.decodeHighSignedNibble(buffer[bufferIndex + 1]);
}
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((litB << 4) | regA);
}
public Format getFormat() {
return Format.Format11n;
}
public int getRegisterA() {
return regA;
}
public long getLiteral() {
return litB;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction11n(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,76 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction11x extends Instruction implements SingleRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
public Instruction11x(Opcode opcode, short regA) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
}
private Instruction11x(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
}
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
}
public Format getFormat() {
return Format.Format11x;
}
public int getRegisterA() {
return regA & 0xFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction11x(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,83 +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.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.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction12x extends Instruction implements TwoRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private int regA;
private int regB;
public Instruction12x(Opcode opcode, byte regA, byte regB) {
super(opcode);
if (regA >= 1 << 4 ||
regB >= 1 << 4) {
throw new RuntimeException("The register number must be less than v16");
}
this.regA = regA;
this.regB = regB;
}
private Instruction12x(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
}
public void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((regB << 4) | regA);
}
public Format getFormat() {
return Format.Format12x;
}
public int getRegisterA() {
return regA;
}
public int getRegisterB() {
return regB;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction12x(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,100 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2011 Ben Gruver
* 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.dexlib.Code.Format;
import org.jf.dexlib.*;
import org.jf.dexlib.Code.*;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction20bc extends InstructionWithReference {
public static final Instruction.InstructionFactory Factory = new Factory();
private VerificationErrorType validationErrorType;
public Instruction20bc(Opcode opcode, VerificationErrorType validationErrorType, Item referencedItem) {
super(opcode, referencedItem, getReferenceType(referencedItem));
this.validationErrorType = validationErrorType;
}
private static ReferenceType getReferenceType(Item item) {
if (item instanceof TypeIdItem) {
return ReferenceType.type;
}
if (item instanceof FieldIdItem) {
return ReferenceType.field;
}
if (item instanceof MethodIdItem) {
return ReferenceType.method;
}
return null;
}
private Instruction20bc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
short val = NumberUtils.decodeUnsignedByte(buffer[bufferIndex+1]);
validationErrorType = VerificationErrorType.getValidationErrorType(val & 0x3f);
}
protected ReferenceType readReferenceType(Opcode opcode, byte[] buffer, int bufferIndex) {
short val = NumberUtils.decodeUnsignedByte(buffer[bufferIndex+1]);
short referenceType = (short)(val >> 6);
return ReferenceType.fromValidationErrorReferenceType(referenceType);
}
@Override
public Format getFormat() {
return Format.Format20bc;
}
@Override
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if(opcode == Opcode.CONST_STRING && getReferencedItem().getIndex() > 0xFFFF) {
throw new RuntimeException("String offset is too large for const-string. Use string-const/jumbo instead.");
}
out.writeByte(opcode.value);
out.writeByte((this.getReferenceType().getValidationErrorReferenceType() << 6) &
validationErrorType.getValue());
out.writeShort(getReferencedItem().getIndex());
}
public VerificationErrorType getValidationErrorType() {
return validationErrorType;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction20bc(dexFile, opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,94 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction20t extends OffsetInstruction {
public static final InstructionFactory Factory = new Factory();
private int targetAddressOffset;
public Instruction20t(Opcode opcode, int offA) {
super(opcode);
this.targetAddressOffset = offA;
if (targetAddressOffset == 0) {
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead.");
}
//allow out of range address offsets here, so we have the option of replacing this instruction
//with goto/16 or goto/32 later
}
private Instruction20t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
assert buffer[bufferIndex] == opcode.value;
this.targetAddressOffset = NumberUtils.decodeShort(buffer, bufferIndex+2);
assert targetAddressOffset != 0;
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if (targetAddressOffset == 0) {
throw new RuntimeException("The address offset cannot be 0. Use goto/32 instead");
}
if (targetAddressOffset < -32768 || targetAddressOffset > 32767) {
throw new RuntimeException("The address offset is out of range. It must be in [-32768,-1] or [1, 32768]");
}
out.writeByte(opcode.value);
out.writeByte(0x00);
out.writeShort(targetAddressOffset);
}
public void updateTargetAddressOffset(int targetAddressOffset) {
this.targetAddressOffset = targetAddressOffset;
}
public Format getFormat() {
return Format.Format20t;
}
public int getTargetAddressOffset() {
return targetAddressOffset;
}
private static class Factory implements InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction20t(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,111 +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.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;
public class Instruction21c extends InstructionWithReference implements SingleRegisterInstruction,
InstructionWithJumboVariant {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
public Instruction21c(Opcode opcode, short regA, Item referencedItem) {
super(opcode, referencedItem);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
if (opcode == Opcode.NEW_INSTANCE) {
assert referencedItem instanceof TypeIdItem;
if (((TypeIdItem)referencedItem).getTypeDescriptor().charAt(0) != 'L') {
throw new RuntimeException("Only class references can be used with the new-instance opcode");
}
}
this.regA = (byte)regA;
}
private Instruction21c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
if (opcode == Opcode.NEW_INSTANCE &&
((TypeIdItem)this.getReferencedItem()).getTypeDescriptor().charAt(0) != 'L') {
throw new RuntimeException("Only class references can be used with the new-instance opcode");
}
this.regA = buffer[bufferIndex + 1];
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if(getReferencedItem().getIndex() > 0xFFFF) {
if (opcode.hasJumboOpcode()) {
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
opcode.referenceType.name(), opcode.getJumboOpcode().name));
} else {
throw new RuntimeException(String.format("%s index is too large", opcode.referenceType.name()));
}
}
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeShort(getReferencedItem().getIndex());
}
public Format getFormat() {
return Format.Format21c;
}
public int getRegisterA() {
return regA & 0xFF;
}
public Instruction makeJumbo() {
Opcode jumboOpcode = opcode.getJumboOpcode();
if (jumboOpcode == null) {
return null;
}
return new Instruction31c(jumboOpcode, (short)getRegisterA(), getReferencedItem());
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction21c(dexFile, opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,94 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.EncodedLiteralInstruction;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction21h extends Instruction implements SingleRegisterInstruction, EncodedLiteralInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private short litB;
public Instruction21h(Opcode opcode, short regA, short litB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.litB = litB;
}
private Instruction21h(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = buffer[bufferIndex + 1];
this.litB = NumberUtils.decodeShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeShort(litB);
}
public Format getFormat() {
return Format.Format21h;
}
public int getRegisterA() {
return regA & 0xFF;
}
public long getLiteral() {
return litB;
}
public long getDecodedLiteral() {
if (opcode == Opcode.CONST_HIGH16) {
return litB << 16;
} else {
assert opcode == Opcode.CONST_WIDE_HIGH16;
return ((long)litB) << 48;
}
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction21h(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,85 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.LiteralInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction21s extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private short litB;
public Instruction21s(Opcode opcode, short regA, short litB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.litB = litB;
}
private Instruction21s(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = buffer[bufferIndex + 1];
this.litB = NumberUtils.decodeShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeShort(litB);
}
public Format getFormat() {
return Format.Format21s;
}
public int getRegisterA() {
return regA & 0xFF;
}
public long getLiteral() {
return litB;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction21s(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,103 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction21t extends OffsetInstruction implements SingleRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private short targetAddressOffset;
public Instruction21t(Opcode opcode, short regA, short offB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
if (offB == 0) {
throw new RuntimeException("The address offset cannot be 0.");
}
this.regA = (byte)regA;
this.targetAddressOffset = offB;
}
private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
assert buffer[bufferIndex] == opcode.value;
regA = buffer[bufferIndex + 1];
targetAddressOffset = NumberUtils.decodeShort(buffer, bufferIndex + 2);
assert targetAddressOffset != 0;
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeShort(targetAddressOffset);
}
public void updateTargetAddressOffset(int targetAddressOffset) {
if (targetAddressOffset < Short.MIN_VALUE || targetAddressOffset > Short.MAX_VALUE) {
throw new RuntimeException("The address offset " + targetAddressOffset +
" is out of range. It must be in [-32768, 32767]");
}
if (targetAddressOffset == 0) {
throw new RuntimeException("The address offset cannot be 0");
}
this.targetAddressOffset = (short) targetAddressOffset;
}
public Format getFormat() {
return Format.Format21t;
}
public int getRegisterA() {
return regA & 0xFF;
}
public int getTargetAddressOffset() {
return targetAddressOffset;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction21t(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,93 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.LiteralInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.TwoRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction22b extends Instruction implements TwoRegisterInstruction, LiteralInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private byte regB;
private byte litC;
public Instruction22b(Opcode opcode, short regA, short regB, byte litC) {
super(opcode);
if (regA >= 1 << 8 ||
regB >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.regB = (byte)regB;
this.litC = litC;
}
private Instruction22b(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = buffer[bufferIndex + 1];
this.regB = buffer[bufferIndex + 2];
this.litC = buffer[bufferIndex + 3];
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeByte(regB);
out.writeByte(litC);
}
public Format getFormat() {
return Format.Format22b;
}
public int getRegisterA() {
return regA & 0xFF;
}
public int getRegisterB() {
return regB & 0xFF;
}
public long getLiteral() {
return litC;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction22b(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,96 +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.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.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 Instruction22c extends InstructionWithReference implements TwoRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private byte regB;
public Instruction22c(Opcode opcode, byte regA, byte regB, Item referencedItem) {
super(opcode, referencedItem);
if (regA >= 1 << 4 ||
regB >= 1 << 4) {
throw new RuntimeException("The register number must be less than v16");
}
this.regA = regA;
this.regB = regB;
}
private Instruction22c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if(getReferencedItem().getIndex() > 0xFFFF) {
if (opcode.hasJumboOpcode()) {
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
opcode.referenceType.name(), opcode.getJumboOpcode().name));
} else {
throw new RuntimeException(String.format("%s index is too large.", opcode.referenceType.name()));
}
}
out.writeByte(opcode.value);
out.writeByte((regB << 4) | regA);
out.writeShort(getReferencedItem().getIndex());
}
public Format getFormat() {
return Format.Format22c;
}
public int getRegisterA() {
return regA;
}
public int getRegisterB() {
return regB;
}
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);
}
}
}

View File

@ -1,97 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OdexedFieldAccess;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.TwoRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction22cs extends Instruction implements TwoRegisterInstruction, OdexedFieldAccess {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private byte regB;
private short fieldOffset;
public Instruction22cs(Opcode opcode, byte regA, byte regB, int fieldOffset) {
super(opcode);
if (regA >= 1 << 4 ||
regB >= 1 << 4) {
throw new RuntimeException("The register number must be less than v16");
}
if (fieldOffset >= 1 << 16) {
throw new RuntimeException("The field offset must be less than 65536");
}
this.regA = regA;
this.regB = regB;
this.fieldOffset = (short)fieldOffset;
}
private Instruction22cs(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
this.fieldOffset = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((regB << 4) | regA);
out.writeShort(fieldOffset);
}
public Format getFormat() {
return Format.Format22cs;
}
public int getRegisterA() {
return regA;
}
public int getRegisterB() {
return regB;
}
public int getFieldOffset() {
return fieldOffset & 0xFFFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction22cs(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,93 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.LiteralInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.TwoRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction22s extends Instruction implements TwoRegisterInstruction, LiteralInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private byte regB;
private short litC;
public Instruction22s(Opcode opcode, byte regA, byte regB, short litC) {
super(opcode);
if (regA >= 1 << 4 ||
regB >= 1 << 4) {
throw new RuntimeException("The register number must be less than v16");
}
this.regA = regA;
this.regB = regB;
this.litC = litC;
}
private Instruction22s(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
this.litC = NumberUtils.decodeShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((regB << 4) | regA);
out.writeShort(litC);
}
public Format getFormat() {
return Format.Format22s;
}
public int getRegisterA() {
return regA;
}
public int getRegisterB() {
return regB;
}
public long getLiteral() {
return litC;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction22s(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,112 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.TwoRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction22t extends OffsetInstruction implements TwoRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private byte regB;
private short targetAddressOffset;
public Instruction22t(Opcode opcode, byte regA, byte regB, short offC) {
super(opcode);
if (regA >= 16 ||
regB >= 16) {
throw new RuntimeException("The register number must be less than v16");
}
if (offC == 0) {
throw new RuntimeException("The address offset cannot be 0.");
}
this.regA = regA;
this.regB = regB;
this.targetAddressOffset = offC;
}
private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
assert buffer[bufferIndex] == opcode.value;
regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
regB = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
targetAddressOffset = NumberUtils.decodeShort(buffer, bufferIndex + 2);
assert targetAddressOffset != 0;
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((regB << 4) | regA);
out.writeShort(targetAddressOffset);
}
public void updateTargetAddressOffset(int targetAddressOffset) {
if (targetAddressOffset < -32768 || targetAddressOffset > 32767) {
throw new RuntimeException("The address offset " + targetAddressOffset +
" is out of range. It must be in [-32768, 32767]");
}
if (targetAddressOffset == 0) {
throw new RuntimeException("The address offset cannot be 0");
}
this.targetAddressOffset = (short)targetAddressOffset;
}
public Format getFormat() {
return Format.Format22t;
}
public int getRegisterA() {
return regA;
}
public int getRegisterB() {
return regB;
}
public int getTargetAddressOffset() {
return targetAddressOffset;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction22t(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,88 +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.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.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction22x extends Instruction implements TwoRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private short regB;
public Instruction22x(Opcode opcode, short regA, int regB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v16");
}
if (regB >= 1 << 16) {
throw new RuntimeException("The register number must be less than v65536");
}
this.regA = (byte)regA;
this.regB = (short)regB;
}
private Instruction22x(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = buffer[bufferIndex + 1];
this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeShort(regB);
}
public Format getFormat() {
return Format.Format22x;
}
public int getRegisterA() {
return regA & 0xFF;
}
public int getRegisterB() {
return regB & 0xFFFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction22x(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,93 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.ThreeRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
public class Instruction23x extends Instruction implements ThreeRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private byte regB;
private byte regC;
public Instruction23x(Opcode opcode, short regA, short regB, short regC) {
super(opcode);
if (regA >= 1 << 8 ||
regB >= 1 << 8 ||
regC >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.regB = (byte)regB;
this.regC = (byte)regC;
}
private Instruction23x(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = buffer[bufferIndex + 1];
this.regB = buffer[bufferIndex + 2];
this.regC = buffer[bufferIndex + 3];
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeByte(regB);
out.writeByte(regC);
}
public Format getFormat() {
return Format.Format23x;
}
public int getRegisterA() {
return regA & 0xFF;
}
public int getRegisterB() {
return regB & 0xFF;
}
public int getRegisterC() {
return regC & 0xFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction23x(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,78 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction30t extends OffsetInstruction {
public static final InstructionFactory Factory = new Factory();
private int targetAddressOffset;
public Instruction30t(Opcode opcode, int offA) {
super(opcode);
this.targetAddressOffset = offA;
}
private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
assert buffer[bufferIndex] == opcode.value;
this.targetAddressOffset = NumberUtils.decodeInt(buffer, bufferIndex+2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(0x00);
out.writeInt(targetAddressOffset);
}
public void updateTargetAddressOffset(int targetAddressOffset) {
this.targetAddressOffset = targetAddressOffset;
}
public Format getFormat() {
return Format.Format30t;
}
public int getTargetAddressOffset() {
return targetAddressOffset;
}
private static class Factory implements InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction30t(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,79 +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.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.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction31c extends InstructionWithJumboReference implements SingleRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
public Instruction31c(Opcode opcode, short regA, Item referencedItem) {
super(opcode, referencedItem);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
}
private Instruction31c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
this.regA = buffer[bufferIndex + 1];
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeInt(getReferencedItem().getIndex());
}
public Format getFormat() {
return Format.Format31c;
}
public int getRegisterA() {
return regA & 0xFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction31c(dexFile, opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,85 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.LiteralInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction31i extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private int litB;
public Instruction31i(Opcode opcode, short regA, int litB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.litB = litB;
}
private Instruction31i(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
this.litB = NumberUtils.decodeInt(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeInt(litB);
}
public Format getFormat() {
return Format.Format31i;
}
public int getRegisterA() {
return regA & 0xFF;
}
public long getLiteral() {
return litB;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction31i(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,90 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction31t extends OffsetInstruction implements SingleRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private int targetAddressOffset;
public Instruction31t(Opcode opcode, short regA, int offB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.targetAddressOffset = offB;
}
private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = buffer[bufferIndex + 1];
this.targetAddressOffset = NumberUtils.decodeInt(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
//align the address offset so that the absolute address is aligned on a 4-byte boundary (2 code block boundary)
out.writeInt(targetAddressOffset + ((currentCodeAddress + targetAddressOffset) % 2));
}
public void updateTargetAddressOffset(int targetAddressOffset) {
this.targetAddressOffset = targetAddressOffset;
}
public Format getFormat() {
return Format.Format31t;
}
public int getRegisterA() {
return regA & 0xFF;
}
public int getTargetAddressOffset() {
return targetAddressOffset;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction31t(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,86 +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.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.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction32x extends Instruction implements TwoRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private short regA;
private short regB;
public Instruction32x(Opcode opcode, int regA, int regB) {
super(opcode);
if (regA >= 1<<16 ||
regB >= 1<<16) {
throw new RuntimeException("The register number must be less than v65536");
}
this.regA = (short)regA;
this.regB = (short)regB;
}
private Instruction32x(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regA = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(0);
out.writeShort(regA);
out.writeShort(regB);
}
public Format getFormat() {
return Format.Format32x;
}
public int getRegisterA() {
return regA & 0xFFFF;
}
public int getRegisterB() {
return regB & 0xFFFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction32x(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,170 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.FiveRegisterInstruction;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.InstructionWithReference;
import org.jf.dexlib.Code.Opcode;
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 Instruction35c extends InstructionWithReference implements FiveRegisterInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regCount;
private byte regA;
private byte regD;
private byte regE;
private byte regF;
private byte regG;
public Instruction35c(Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
byte regA, Item referencedItem) {
super(opcode, referencedItem);
if (regCount > 5) {
throw new RuntimeException("regCount cannot be greater than 5");
}
if (regD >= 1 << 4 ||
regE >= 1 << 4 ||
regF >= 1 << 4 ||
regG >= 1 << 4 ||
regA >= 1 << 4) {
throw new RuntimeException("All register args must fit in 4 bits");
}
checkItem(opcode, referencedItem, regCount);
this.regCount = (byte)regCount;
this.regA = regA;
this.regD = regD;
this.regE = regE;
this.regF = regF;
this.regG = regG;
}
protected Instruction35c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
this.regCount = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regD = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]);
this.regE = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 4]);
this.regF = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]);
this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
if (getRegCount() > 5) {
throw new RuntimeException("regCount cannot be greater than 5");
}
checkItem(opcode, getReferencedItem(), getRegCount());
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if(getReferencedItem().getIndex() > 0xFFFF) {
if (opcode.hasJumboOpcode()) {
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
opcode.referenceType.name(), opcode.getJumboOpcode().name));
} else {
throw new RuntimeException(String.format("%s index is too large.", opcode.referenceType.name()));
}
}
out.writeByte(opcode.value);
out.writeByte((regCount << 4) | regA);
out.writeShort(getReferencedItem().getIndex());
out.writeByte((regE << 4) | regD);
out.writeByte((regG << 4) | regF);
}
public Format getFormat() {
return Format.Format35c;
}
public int getRegCount() {
return regCount;
}
public byte getRegisterA() {
return regA;
}
public byte getRegisterD() {
return regD;
}
public byte getRegisterE() {
return regE;
}
public byte getRegisterF() {
return regF;
}
public byte getRegisterG() {
return regG;
}
private static void checkItem(Opcode opcode, Item item, int regCount) {
if (opcode == FILLED_NEW_ARRAY) {
//check data for filled-new-array 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.value && opcode.value <= INVOKE_INTERFACE.value ||
opcode == INVOKE_DIRECT_EMPTY) {
//check data for invoke-* opcodes
MethodIdItem methodIdItem = (MethodIdItem) item;
int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount();
if (opcode != INVOKE_STATIC) {
parameterRegisterCount++;
}
if (parameterRegisterCount != regCount) {
throw new RuntimeException("regCount does not match the number of arguments of the method");
}
}
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction35c(dexFile, opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,136 +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.*;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction35mi extends Instruction implements FiveRegisterInstruction, OdexedInvokeInline {
public static final InstructionFactory Factory = new Factory();
private byte regCount;
private byte regA;
private byte regD;
private byte regE;
private byte regF;
private byte regG;
private short inlineIndex;
public Instruction35mi(Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
byte regA, int inlineIndex) {
super(opcode);
if (regCount > 5) {
throw new RuntimeException("regCount cannot be greater than 5");
}
if (regD >= 1 << 4 ||
regE >= 1 << 4 ||
regF >= 1 << 4 ||
regG >= 1 << 4 ||
regA >= 1 << 4) {
throw new RuntimeException("All register args must fit in 4 bits");
}
if (inlineIndex >= 1 << 16) {
throw new RuntimeException("The method index must be less than 65536");
}
this.regCount = (byte)regCount;
this.regA = regA;
this.regD = regD;
this.regE = regE;
this.regF = regF;
this.regG = regG;
this.inlineIndex = (short)inlineIndex;
}
private Instruction35mi(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regCount = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regD = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]);
this.regE = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 4]);
this.regF = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]);
this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
this.inlineIndex = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((regCount << 4) | regA);
out.writeShort(inlineIndex);
out.writeByte((regE << 4) | regD);
out.writeByte((regG << 4) | regF);
}
public Format getFormat() {
return Format.Format35mi;
}
public int getRegCount() {
return regCount;
}
public byte getRegisterA() {
return regA;
}
public byte getRegisterD() {
return regD;
}
public byte getRegisterE() {
return regE;
}
public byte getRegisterF() {
return regF;
}
public byte getRegisterG() {
return regG;
}
public int getInlineIndex() {
return inlineIndex & 0xFFFF;
}
private static class Factory implements InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction35mi(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,136 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.FiveRegisterInstruction;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OdexedInvokeVirtual;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction35ms extends Instruction implements FiveRegisterInstruction, OdexedInvokeVirtual {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regCount;
private byte regA;
private byte regD;
private byte regE;
private byte regF;
private byte regG;
private short vtableIndex;
public Instruction35ms(Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
byte regA, int vtableIndex) {
super(opcode);
if (regCount > 5) {
throw new RuntimeException("regCount cannot be greater than 5");
}
if (regD >= 1 << 4 ||
regE >= 1 << 4 ||
regF >= 1 << 4 ||
regG >= 1 << 4 ||
regA >= 1 << 4) {
throw new RuntimeException("All register args must fit in 4 bits");
}
if (vtableIndex >= 1 << 16) {
throw new RuntimeException("The method index must be less than 65536");
}
this.regCount = (byte)regCount;
this.regA = regA;
this.regD = regD;
this.regE = regE;
this.regF = regF;
this.regG = regG;
this.vtableIndex = (short)vtableIndex;
}
private Instruction35ms(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regCount = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
this.regA = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
this.regD = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]);
this.regE = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 4]);
this.regF = NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]);
this.regG = NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
this.vtableIndex = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte((regCount << 4) | regA);
out.writeShort(vtableIndex);
out.writeByte((regE << 4) | regD);
out.writeByte((regG << 4) | regF);
}
public Format getFormat() {
return Format.Format35ms;
}
public int getRegCount() {
return regCount;
}
public byte getRegisterA() {
return regA;
}
public byte getRegisterD() {
return regD;
}
public byte getRegisterE() {
return regE;
}
public byte getRegisterF() {
return regF;
}
public byte getRegisterG() {
return regG;
}
public int getVtableIndex() {
return vtableIndex & 0xFFFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction35ms(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,138 +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.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 Instruction3rc extends InstructionWithReference implements RegisterRangeInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regCount;
private short startReg;
public Instruction3rc(Opcode opcode, short regCount, int startReg, Item referencedItem) {
super(opcode, referencedItem);
if (regCount >= 1 << 8) {
throw new RuntimeException("regCount must be less than 256");
}
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 = (byte)regCount;
this.startReg = (short)startReg;
checkItem(opcode, referencedItem, regCount);
}
private Instruction3rc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
this.regCount = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
this.startReg = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
checkItem(opcode, getReferencedItem(), getRegCount());
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
if(getReferencedItem().getIndex() > 0xFFFF) {
if (opcode.hasJumboOpcode()) {
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
opcode.referenceType.name(), opcode.getJumboOpcode().name));
} else {
throw new RuntimeException(String.format("%s index is too large.", opcode.referenceType.name()));
}
}
out.writeByte(opcode.value);
out.writeByte(regCount);
out.writeShort(this.getReferencedItem().getIndex());
out.writeShort(startReg);
}
public Format getFormat() {
return Format.Format3rc;
}
public int getRegCount() {
return (short)(regCount & 0xFF);
}
public int getStartRegister() {
return startReg & 0xFFFF;
}
private static void checkItem(Opcode opcode, Item item, int regCount) {
if (opcode == FILLED_NEW_ARRAY_RANGE) {
//check data for filled-new-array/range 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_RANGE.value && opcode.value <= INVOKE_INTERFACE_RANGE.value ||
opcode == INVOKE_OBJECT_INIT_RANGE) {
//check data for invoke-*/range opcodes
MethodIdItem methodIdItem = (MethodIdItem) item;
int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount();
if (opcode != INVOKE_STATIC_RANGE) {
parameterRegisterCount++;
}
if (parameterRegisterCount != regCount) {
throw new RuntimeException("regCount does not match the number of arguments of the method");
}
}
}
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);
}
}
}

View File

@ -1,107 +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.*;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction3rmi extends Instruction implements RegisterRangeInstruction, OdexedInvokeInline {
public static final InstructionFactory Factory = new Factory();
private byte regCount;
private short startReg;
private short inlineIndex;
public Instruction3rmi(Opcode opcode, short regCount, int startReg, int inlineIndex) {
super(opcode);
if (regCount >= 1 << 8) {
throw new RuntimeException("regCount must be less than 256");
}
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");
}
if (inlineIndex >= 1 << 16) {
throw new RuntimeException("The method index must be less than 65536");
}
this.regCount = (byte)regCount;
this.startReg = (short)startReg;
this.inlineIndex = (short)inlineIndex;
}
private Instruction3rmi(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regCount = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
this.inlineIndex = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
this.startReg = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regCount);
out.writeShort(inlineIndex);
out.writeShort(startReg);
}
public Format getFormat() {
return Format.Format3rmi;
}
public int getRegCount() {
return (short)(regCount & 0xFF);
}
public int getStartRegister() {
return startReg & 0xFFFF;
}
public int getInlineIndex() {
return inlineIndex & 0xFFFF;
}
private static class Factory implements InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction3rmi(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,107 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.OdexedInvokeVirtual;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.RegisterRangeInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction3rms extends Instruction implements RegisterRangeInstruction, OdexedInvokeVirtual {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regCount;
private short startReg;
private short vtableIndex;
public Instruction3rms(Opcode opcode, short regCount, int startReg, int vtableIndex) {
super(opcode);
if (regCount >= 1 << 8) {
throw new RuntimeException("regCount must be less than 256");
}
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");
}
if (vtableIndex >= 1 << 16) {
throw new RuntimeException("The method index must be less than 65536");
}
this.regCount = (byte)regCount;
this.startReg = (short)startReg;
this.vtableIndex = (short)vtableIndex;
}
private Instruction3rms(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.regCount = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
this.vtableIndex = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
this.startReg = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regCount);
out.writeShort(vtableIndex);
out.writeShort(startReg);
}
public Format getFormat() {
return Format.Format3rms;
}
public int getRegCount() {
return (short)(regCount & 0xFF);
}
public int getStartRegister() {
return startReg & 0xFFFF;
}
public int getVtableIndex() {
return vtableIndex & 0xFFFF;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction3rms(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,85 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.LiteralInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.SingleRegisterInstruction;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
public class Instruction51l extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private byte regA;
private long litB;
public Instruction51l(Opcode opcode, short regA, long litB) {
super(opcode);
if (regA >= 1 << 8) {
throw new RuntimeException("The register number must be less than v256");
}
this.regA = (byte)regA;
this.litB = litB;
}
private Instruction51l(Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
regA = (byte)NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
litB = NumberUtils.decodeLong(buffer, bufferIndex + 2);
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.writeByte(opcode.value);
out.writeByte(regA);
out.writeLong(litB);
}
public Format getFormat() {
return Format.Format51l;
}
public int getRegisterA() {
return regA & 0xFF;
}
public long getLiteral() {
return litB;
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
return new Instruction51l(opcode, buffer, bufferIndex);
}
}
}

View File

@ -1,57 +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.InstructionWithReference;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.Code.ReferenceType;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Item;
import org.jf.dexlib.Util.NumberUtils;
public abstract class InstructionWithJumboReference extends InstructionWithReference {
protected InstructionWithJumboReference(Opcode opcode, Item referencedItem) {
super(opcode, referencedItem);
}
protected InstructionWithJumboReference(Opcode opcode, Item referencedItem, ReferenceType referenceType) {
super(opcode, referencedItem, referenceType);
}
protected InstructionWithJumboReference(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(dexFile, opcode, buffer, bufferIndex);
}
protected int getReferencedItemIndex(byte[] buffer, int bufferIndex) {
return NumberUtils.decodeInt(buffer, bufferIndex + 2);
}
}

View File

@ -1,38 +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;
public interface InstructionWithJumboVariant {
Instruction makeJumbo();
}

View File

@ -1,158 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.MultiOffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
import java.util.Iterator;
public class PackedSwitchDataPseudoInstruction extends Instruction implements MultiOffsetInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private int firstKey;
private int[] targets;
@Override
public int getSize(int codeAddress) {
return getTargetCount() * 2 + 4 + (codeAddress % 2);
}
public PackedSwitchDataPseudoInstruction(int firstKey, int[] targets) {
super(Opcode.NOP);
if (targets.length > 0xFFFF) {
throw new RuntimeException("The packed-switch data contains too many elements. " +
"The maximum number of switch elements is 65535");
}
this.firstKey = firstKey;
this.targets = targets;
}
public PackedSwitchDataPseudoInstruction(byte[] buffer, int bufferIndex) {
super(Opcode.NOP);
byte opcodeByte = buffer[bufferIndex];
if (opcodeByte != 0x00) {
throw new RuntimeException("Invalid opcode byte for a PackedSwitchData pseudo-instruction");
}
byte subopcodeByte = buffer[bufferIndex+1];
if (subopcodeByte != 0x01) {
throw new RuntimeException("Invalid sub-opcode byte for a PackedSwitchData pseudo-instruction");
}
int targetCount = NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
this.firstKey = NumberUtils.decodeInt(buffer, bufferIndex + 4);
this.targets = new int[targetCount];
for (int i = 0; i<targetCount; i++) {
targets[i] = NumberUtils.decodeInt(buffer, bufferIndex + 8 + 4*i);
}
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.alignTo(4);
out.writeByte(0x00);
out.writeByte(0x01);
out.writeShort(targets.length);
out.writeInt(firstKey);
for (int target : targets) {
out.writeInt(target);
}
}
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
"packed-switch-data instruction");
}
public void updateTarget(int targetIndex, int targetAddressOffset) {
targets[targetIndex] = targetAddressOffset;
}
public Format getFormat() {
return Format.PackedSwitchData;
}
public int getTargetCount() {
return targets.length;
}
public int getFirstKey() {
return firstKey;
}
public int[] getTargets() {
return targets;
}
public static class PackedSwitchTarget {
public int value;
public int targetAddressOffset;
}
public Iterator<PackedSwitchTarget> iterateKeysAndTargets() {
return new Iterator<PackedSwitchTarget>() {
final int targetCount = getTargetCount();
int i = 0;
int value = getFirstKey();
PackedSwitchTarget packedSwitchTarget = new PackedSwitchTarget();
public boolean hasNext() {
return i<targetCount;
}
public PackedSwitchTarget next() {
packedSwitchTarget.value = value++;
packedSwitchTarget.targetAddressOffset = targets[i];
i++;
return packedSwitchTarget;
}
public void remove() {
}
};
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
if (opcode != Opcode.NOP) {
throw new RuntimeException("The opcode for a PackedSwitchDataPseudoInstruction must be NOP");
}
return new PackedSwitchDataPseudoInstruction(buffer, bufferIndex);
}
}
}

View File

@ -1,177 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Code.MultiOffsetInstruction;
import org.jf.dexlib.Code.Opcode;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.NumberUtils;
import java.util.Iterator;
public class SparseSwitchDataPseudoInstruction extends Instruction implements MultiOffsetInstruction {
public static final Instruction.InstructionFactory Factory = new Factory();
private int[] keys;
private int[] targets;
@Override
public int getSize(int codeAddress) {
return getTargetCount() * 4 + 2 + (codeAddress % 2);
}
public SparseSwitchDataPseudoInstruction(int[] keys, int[] targets) {
super(Opcode.NOP);
if (keys.length != targets.length) {
throw new RuntimeException("The number of keys and targets don't match");
}
if (targets.length == 0) {
throw new RuntimeException("The sparse-switch data must contain at least 1 key/target");
}
if (targets.length > 0xFFFF) {
throw new RuntimeException("The sparse-switch data contains too many elements. " +
"The maximum number of switch elements is 65535");
}
this.keys = keys;
this.targets = targets;
}
public SparseSwitchDataPseudoInstruction(byte[] buffer, int bufferIndex) {
super(Opcode.NOP);
byte opcodeByte = buffer[bufferIndex];
if (opcodeByte != 0x00) {
throw new RuntimeException("Invalid opcode byte for a SparseSwitchData pseudo-instruction");
}
byte subopcodeByte = buffer[bufferIndex+1];
if (subopcodeByte != 0x02) {
throw new RuntimeException("Invalid sub-opcode byte for a SparseSwitchData pseudo-instruction");
}
int targetCount = NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
keys = new int[targetCount];
targets = new int[targetCount];
for (int i=0; i<targetCount; i++) {
keys[i] = NumberUtils.decodeInt(buffer, bufferIndex + 4 + i*4);
targets[i] = NumberUtils.decodeInt(buffer, bufferIndex + 4 + targetCount*4 + i*4);
}
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.alignTo(4);
out.writeByte(0x00);
out.writeByte(0x02);
out.writeShort(targets.length);
if (targets.length > 0) {
int key = keys[0];
out.writeInt(key);
for (int i = 1; i < keys.length; i++) {
key = keys[i];
assert key >= keys[i - 1];
out.writeInt(key);
}
for (int target : targets) {
out.writeInt(target);
}
}
}
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
"sparse-switch-data instruction");
}
public void updateTarget(int targetIndex, int targetAddressOffset) {
targets[targetIndex] = targetAddressOffset;
}
public Format getFormat() {
return Format.SparseSwitchData;
}
public int getTargetCount() {
return targets.length;
}
public int[] getTargets() {
return targets;
}
public int[] getKeys() {
return keys;
}
public static class SparseSwitchTarget {
public int key;
public int targetAddressOffset;
}
public Iterator<SparseSwitchTarget> iterateKeysAndTargets() {
return new Iterator<SparseSwitchTarget>() {
final int targetCount = getTargetCount();
int i = 0;
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
public boolean hasNext() {
return i<targetCount;
}
public SparseSwitchTarget next() {
sparseSwitchTarget.key = keys[i];
sparseSwitchTarget.targetAddressOffset = targets[i];
i++;
return sparseSwitchTarget;
}
public void remove() {
}
};
}
private static class Factory implements Instruction.InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
if (opcode != Opcode.NOP) {
throw new RuntimeException("The opcode for a SparseSwitchDataPseudoInstruction must be NOP");
}
return new SparseSwitchDataPseudoInstruction(buffer, bufferIndex);
}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR 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.Opcode;
public class UnknownInstruction extends Instruction10x {
private short originalOpcode;
public UnknownInstruction(short originalOpcode) {
super(Opcode.NOP);
this.originalOpcode = originalOpcode;
}
public short getOriginalOpcode() {
return originalOpcode;
}
}

View File

@ -1,62 +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.dexlib.Code.Format;
import org.jf.dexlib.Code.Instruction;
import org.jf.dexlib.Util.AnnotatedOutput;
/**
* 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 extends 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) {
super(originalInstruction.opcode);
this.OriginalInstruction = originalInstruction;
this.ObjectRegisterNum = objectRegisterNumber;
}
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
throw new RuntimeException("Cannot rewrite an instruction that couldn't be deodexed");
}
@Override
public int getSize(int codeAddress) {
return OriginalInstruction.getSize(codeAddress);
}
public Format getFormat() {
return Format.UnresolvedOdexInstruction;
}
}

View File

@ -1,71 +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.dexlib.Code;
import org.jf.dexlib.Code.Format.Format;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
public abstract class Instruction {
public final Opcode opcode;
/**
* Returns the size of this instruction in code blocks, assuming the instruction is located at the given address
* @param codeAddress the code address where the instruction is located
* @return The size of this instruction in code blocks
**/
public int getSize(int codeAddress) {
return opcode.format.size/2;
}
protected Instruction(Opcode opcode) {
this.opcode = opcode;
}
public abstract Format getFormat();
public int write(AnnotatedOutput out, int currentCodeAddress) {
if (out.annotates()) {
annotateInstruction(out, currentCodeAddress);
}
writeInstruction(out, currentCodeAddress);
return currentCodeAddress + getSize(currentCodeAddress);
}
protected void annotateInstruction(AnnotatedOutput out, int currentCodeAddress) {
out.annotate(getSize(currentCodeAddress)*2, "[0x" + Integer.toHexString(currentCodeAddress) + "] " +
opcode.name + " instruction");
}
protected abstract void writeInstruction(AnnotatedOutput out, int currentCodeAddress);
public static interface InstructionFactory {
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex);
}
}

View File

@ -1,98 +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.dexlib.Code;
import org.jf.dexlib.Code.Format.*;
import org.jf.dexlib.DexFile;
import org.jf.util.ExceptionWithContext;
public class InstructionIterator {
public static void IterateInstructions(DexFile dexFile, byte[] insns, ProcessInstructionDelegate delegate) {
int insnsPosition = 0;
while (insnsPosition < insns.length) {
try
{
short opcodeValue = (short)(insns[insnsPosition] & 0xFF);
if (opcodeValue == 0xFF) {
opcodeValue = (short)((0xFF << 8) | insns[insnsPosition+1]);
}
Opcode opcode = Opcode.getOpcodeByValue(opcodeValue);
Instruction instruction = null;
if (opcode == null) {
System.err.println(String.format("unknown opcode encountered - %x. Treating as nop.",
(opcodeValue & 0xFFFF)));
instruction = new UnknownInstruction(opcodeValue);
} else {
if (opcode == Opcode.NOP) {
byte secondByte = insns[insnsPosition + 1];
switch (secondByte) {
case 0:
{
instruction = new Instruction10x(Opcode.NOP, insns, insnsPosition);
break;
}
case 1:
{
instruction = new PackedSwitchDataPseudoInstruction(insns, insnsPosition);
break;
}
case 2:
{
instruction = new SparseSwitchDataPseudoInstruction(insns, insnsPosition);
break;
}
case 3:
{
instruction = new ArrayDataPseudoInstruction(insns, insnsPosition);
break;
}
}
} else {
instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, insns, insnsPosition);
}
}
assert instruction != null;
delegate.ProcessInstruction(insnsPosition/2, instruction);
insnsPosition += instruction.getSize(insnsPosition/2)*2;
} catch (Exception ex) {
throw ExceptionWithContext.withContext(ex, "Error occured at code address " + insnsPosition * 2);
}
}
}
public static interface ProcessInstructionDelegate {
public void ProcessInstruction(int codeAddress, Instruction instruction);
}
}

View File

@ -1,126 +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.dexlib.Code;
import org.jf.dexlib.*;
import org.jf.dexlib.Util.NumberUtils;
public abstract class InstructionWithReference extends Instruction {
private Item referencedItem;
private ReferenceType referenceType;
protected InstructionWithReference(Opcode opcode, Item referencedItem) {
super(opcode);
this.referencedItem = referencedItem;
this.referenceType = opcode.referenceType;
checkReferenceType();
}
protected InstructionWithReference(Opcode opcode, Item referencedItem, ReferenceType referenceType) {
super(opcode);
this.referencedItem = referencedItem;
this.referenceType = referenceType;
checkReferenceType();
}
protected InstructionWithReference(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
super(opcode);
this.referenceType = readReferenceType(opcode, buffer, bufferIndex);
int itemIndex = getReferencedItemIndex(buffer, bufferIndex);
lookupReferencedItem(dexFile, opcode, itemIndex);
}
protected int getReferencedItemIndex(byte[] buffer, int bufferIndex) {
return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
}
public ReferenceType getReferenceType() {
return referenceType;
}
public Item getReferencedItem() {
return referencedItem;
}
protected ReferenceType readReferenceType(Opcode opcode, byte[] buffer, int bufferIndex) {
return opcode.referenceType;
}
private void lookupReferencedItem(DexFile dexFile, Opcode opcode, int itemIndex) {
switch (referenceType) {
case field:
referencedItem = dexFile.FieldIdsSection.getItemByIndex(itemIndex);
return;
case method:
referencedItem = dexFile.MethodIdsSection.getItemByIndex(itemIndex);
return;
case type:
referencedItem = dexFile.TypeIdsSection.getItemByIndex(itemIndex);
return;
case string:
referencedItem = dexFile.StringIdsSection.getItemByIndex(itemIndex);
}
}
private void checkReferenceType() {
switch (referenceType) {
case field:
if (!(referencedItem instanceof FieldIdItem)) {
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
" is the wrong item type for opcode " + opcode.name + ". Expecting FieldIdItem.");
}
return;
case method:
if (!(referencedItem instanceof MethodIdItem)) {
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
" is the wrong item type for opcode " + opcode.name + ". Expecting MethodIdItem.");
}
return;
case type:
if (!(referencedItem instanceof TypeIdItem)) {
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
" is the wrong item type for opcode " + opcode.name + ". Expecting TypeIdItem.");
}
return;
case string:
if (!(referencedItem instanceof StringIdItem)) {
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
" is the wrong item type for opcode " + opcode.name + ". Expecting StringIdItem.");
}
return;
default:
if (referencedItem != null) {
throw new RuntimeException(referencedItem.getClass().getSimpleName() +
" is invalid for opcode " + opcode.name + ". This opcode does not reference an item");
}
}
}
}

View File

@ -1,33 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2011 Ben Gruver
* 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.dexlib.Code;
public interface InvokeInstruction {
int getRegCount();
}

View File

@ -1,33 +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.dexlib.Code;
public interface LiteralInstruction {
long getLiteral();
}

View File

@ -1,34 +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.dexlib.Code;
public interface MultiOffsetInstruction {
public int[] getTargets();
public void updateTarget(int targetIndex, int targetAddressOffset);
}

View File

@ -1,33 +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.dexlib.Code;
public interface OdexedFieldAccess {
int getFieldOffset();
}

View File

@ -1,36 +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;
public interface OdexedInvokeInline extends InvokeInstruction {
int getInlineIndex();
}

View File

@ -1,33 +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.dexlib.Code;
public interface OdexedInvokeVirtual {
int getVtableIndex();
}

View File

@ -1,38 +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.dexlib.Code;
public abstract class OffsetInstruction extends Instruction {
protected OffsetInstruction(Opcode opcode) {
super(opcode);
}
public abstract int getTargetAddressOffset();
public abstract void updateTargetAddressOffset(int targetAddressOffset);
}

View File

@ -1,471 +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.dexlib.Code;
import org.jf.dexlib.Code.Format.Format;
import java.util.HashMap;
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.Format21h, 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.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),
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", 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", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
SGET_VOLATILE((short)0xe5, "sget-volatile", 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", 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", 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", 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", 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", 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", 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", 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", ReferenceType.none, Format.Format3rmi, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_DIRECT_EMPTY((short)0xf0, "invoke-direct-empty", 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", 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", 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", 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);
private static Opcode[] opcodesByValue;
private static Opcode[] expandedOpcodesByValue;
private static HashMap<Integer, Opcode> opcodesByName;
//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;
static {
opcodesByValue = new Opcode[256];
expandedOpcodesByValue = new Opcode[256];
opcodesByName = new HashMap<Integer, Opcode>();
for (Opcode opcode: Opcode.values()) {
//INVOKE_DIRECT_EMPTY was changed to INVOKE_OBJECT_INIT_RANGE in ICS
if (opcode != INVOKE_DIRECT_EMPTY) {
if (((opcode.value >> 8) & 0xFF) == 0x00) {
opcodesByValue[opcode.value & 0xFF] = opcode;
} else {
assert ((opcode.value >> 8) & 0xFF) == 0xFF;
expandedOpcodesByValue[opcode.value & 0xFF] = opcode;
}
opcodesByName.put(opcode.name.hashCode(), opcode);
}
}
}
public static Opcode getOpcodeByName(String opcodeName) {
return opcodesByName.get(opcodeName.toLowerCase().hashCode());
}
public static Opcode getOpcodeByValue(short opcodeValue) {
if (((opcodeValue >> 8) & 0xFF) == 0x00) {
return opcodesByValue[opcodeValue & 0xFF];
} else {
assert ((opcodeValue >> 8) & 0xFF) == 0xFF;
return expandedOpcodesByValue[opcodeValue & 0xFF];
}
}
private static void removeOpcodes(Opcode... toRemove) {
for (Opcode opcode: toRemove) {
opcodesByName.remove(opcode.name.toLowerCase().hashCode());
if (((opcode.value >> 8) & 0xFF) == 0x00) {
opcodesByValue[opcode.value] = null;
} else {
expandedOpcodesByValue[opcode.value & 0xFF] = null;
}
}
}
private static void addOpcodes(Opcode... toAdd) {
for (Opcode opcode: toAdd) {
if (((opcode.value >> 8) & 0xFF) == 0x00) {
opcodesByValue[opcode.value & 0xFF] = opcode;
} else {
assert ((opcode.value >> 8) & 0xFF) == 0xFF;
expandedOpcodesByValue[opcode.value & 0xFF] = opcode;
}
opcodesByName.put(opcode.name.hashCode(), opcode);
}
}
/**
* This will add/remove/replace various opcodes in the value/name maps as needed,
* based on the idiosyncrasies of that api level
* @param apiLevel
*/
public static void updateMapsForApiLevel(int apiLevel) {
if (apiLevel < 5) {
removeOpcodes(THROW_VERIFICATION_ERROR);
}
if (apiLevel < 8) {
removeOpcodes(EXECUTE_INLINE_RANGE);
}
if (apiLevel < 9) {
removeOpcodes(IGET_VOLATILE, IPUT_VOLATILE, SGET_VOLATILE, SPUT_VOLATILE, IGET_OBJECT_VOLATILE,
IGET_WIDE_VOLATILE, IPUT_WIDE_VOLATILE, SGET_WIDE_VOLATILE, SPUT_WIDE_VOLATILE,
IPUT_OBJECT_VOLATILE, SGET_OBJECT_VOLATILE, SPUT_OBJECT_VOLATILE);
}
if (apiLevel < 11) {
removeOpcodes(RETURN_VOID_BARRIER);
}
if (apiLevel < 14) {
removeOpcodes(INVOKE_OBJECT_INIT_RANGE);
addOpcodes(INVOKE_DIRECT_EMPTY);
}
}
public final short value;
public final String name;
public final ReferenceType referenceType;
public final Format format;
public final int flags;
private final short jumboOpcode;
Opcode(short opcodeValue, String opcodeName, ReferenceType referenceType, Format format) {
this(opcodeValue, opcodeName, referenceType, format, 0);
}
Opcode(short opcodeValue, String opcodeName, ReferenceType referenceType, Format format, int flags) {
this(opcodeValue, opcodeName, referenceType, format, flags, (short)-1);
}
Opcode(short opcodeValue, String opcodeName, ReferenceType referenceType, Format format, int flags, short jumboOpcodeValue) {
this.value = opcodeValue;
this.name = opcodeName;
this.referenceType = referenceType;
this.format = format;
this.flags = flags;
this.jumboOpcode = jumboOpcodeValue;
}
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;
}
public final boolean hasJumboOpcode() {
return jumboOpcode != -1 && Opcode.getOpcodeByValue(jumboOpcode) != null;
}
public final Opcode getJumboOpcode() {
return Opcode.getOpcodeByValue(jumboOpcode);
}
}

View File

@ -1,80 +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.dexlib.Code;
import org.jf.dexlib.*;
public enum ReferenceType
{
string(-1),
type(0),
field(1),
method(2),
none(-1);
private int validationErrorReferenceType;
private ReferenceType(int validationErrorReferenceType) {
this.validationErrorReferenceType = validationErrorReferenceType;
}
public boolean checkItem(Item item) {
switch (this) {
case string:
return item instanceof StringIdItem;
case type:
return item instanceof TypeIdItem;
case field:
return item instanceof FieldIdItem;
case method:
return item instanceof MethodIdItem;
}
return false;
}
public static ReferenceType fromValidationErrorReferenceType(int validationErrorReferenceType) {
switch (validationErrorReferenceType) {
case 0:
return type;
case 1:
return field;
case 2:
return method;
}
return null;
}
public int getValidationErrorReferenceType() {
if (validationErrorReferenceType == -1) {
throw new RuntimeException("This reference type cannot be referenced from a throw-validation-error" +
" instruction");
}
return validationErrorReferenceType;
}
}

View File

@ -1,33 +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.dexlib.Code;
public interface RegisterRangeInstruction extends InvokeInstruction {
int getStartRegister();
}

View File

@ -1,33 +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.dexlib.Code;
public interface SingleRegisterInstruction {
int getRegisterA();
}

View File

@ -1,33 +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.dexlib.Code;
public interface ThreeRegisterInstruction extends TwoRegisterInstruction {
int getRegisterC();
}

View File

@ -1,35 +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.dexlib.Code;
public interface TwoRegisterInstruction extends SingleRegisterInstruction {
int getRegisterA();
int getRegisterB();
}

View File

@ -1,99 +0,0 @@
/*
* [The "BSD licence"]
* Copyright (c) 2011 Ben Gruver
* 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.dexlib.Code;
import java.util.HashMap;
public enum VerificationErrorType {
None(0, "no-error"),
Generic(1, "generic-error"),
NoClass(2, "no-such-class"),
NoField(3, "no-such-field"),
NoMethod(4, "no-such-method"),
AccessClass(5, "illegal-class-access"),
AccessField(6, "illegal-field-access"),
AccessMethod(7, "illegal-method-access"),
ClassChange(8, "class-change-error"),
Instantiation(9, "instantiation-error");
private static HashMap<String, VerificationErrorType> verificationErrorTypesByName;
static {
verificationErrorTypesByName = new HashMap<String, VerificationErrorType>();
for (VerificationErrorType verificationErrorType: VerificationErrorType.values()) {
verificationErrorTypesByName.put(verificationErrorType.getName(), verificationErrorType);
}
}
private int value;
private String name;
private VerificationErrorType(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
public static VerificationErrorType fromString(String validationErrorType) {
return verificationErrorTypesByName.get(validationErrorType);
}
public static VerificationErrorType getValidationErrorType(int validationErrorType) {
switch (validationErrorType) {
case 0:
return None;
case 1:
return Generic;
case 2:
return NoClass;
case 3:
return NoField;
case 4:
return NoMethod;
case 5:
return AccessClass;
case 6:
return AccessField;
case 7:
return AccessMethod;
case 8:
return ClassChange;
case 9:
return Instantiation;
}
return null;
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR 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;
/**
* Describes an object that can be converted to a different type
*/
public interface Convertible<T> {
T convert();
}

View File

@ -1,364 +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.dexlib.Debug;
import org.jf.dexlib.DebugInfoItem;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.StringIdItem;
import org.jf.dexlib.TypeIdItem;
import org.jf.dexlib.Util.ByteArrayInput;
import org.jf.dexlib.Util.Input;
public class DebugInstructionIterator {
/**
* This method decodes the debug instructions in the given byte array and iterates over them, calling
* the ProcessDebugInstructionDelegate.ProcessDebugInstruction method for each instruction
* @param in an Input object that the debug instructions can be read from
* @param processDebugInstruction a <code>ProcessDebugInstructionDelegate</code> object that gets called
* for each instruction that is encountered
*/
public static void IterateInstructions(Input in, ProcessRawDebugInstructionDelegate processDebugInstruction) {
int startDebugOffset;
while(true)
{
startDebugOffset = in.getCursor();
byte debugOpcode = in.readByte();
switch (debugOpcode) {
case 0x00:
{
processDebugInstruction.ProcessEndSequence(startDebugOffset);
return;
}
case 0x01:
{
int codeAddressDiff = in.readUnsignedLeb128();
processDebugInstruction.ProcessAdvancePC(startDebugOffset, in.getCursor() - startDebugOffset,
codeAddressDiff);
break;
}
case 0x02:
{
int lineDiff = in.readSignedLeb128();
processDebugInstruction.ProcessAdvanceLine(startDebugOffset, in.getCursor() - startDebugOffset,
lineDiff);
break;
}
case 0x03:
{
int registerNum = in.readUnsignedOrSignedLeb128();
boolean isSignedRegister = false;
if (registerNum < 0) {
isSignedRegister = true;
registerNum = ~registerNum;
}
int nameIndex = in.readUnsignedLeb128() - 1;
int typeIndex = in.readUnsignedLeb128() - 1;
processDebugInstruction.ProcessStartLocal(startDebugOffset, in.getCursor() - startDebugOffset,
registerNum, nameIndex, typeIndex, isSignedRegister);
break;
}
case 0x04:
{
int registerNum = in.readUnsignedOrSignedLeb128();
boolean isSignedRegister = false;
if (registerNum < 0) {
isSignedRegister = true;
registerNum = ~registerNum;
}
int nameIndex = in.readUnsignedLeb128() - 1;
int typeIndex = in.readUnsignedLeb128() - 1;
int signatureIndex = in.readUnsignedLeb128() - 1;
processDebugInstruction.ProcessStartLocalExtended(startDebugOffset,
in.getCursor() - startDebugOffset, registerNum, nameIndex, typeIndex, signatureIndex,
isSignedRegister);
break;
}
case 0x05:
{
int registerNum = in.readUnsignedOrSignedLeb128();
boolean isSignedRegister = false;
if (registerNum < 0) {
isSignedRegister = true;
registerNum = ~registerNum;
}
processDebugInstruction.ProcessEndLocal(startDebugOffset, in.getCursor() - startDebugOffset,
registerNum, isSignedRegister);
break;
}
case 0x06:
{
int registerNum = in.readUnsignedOrSignedLeb128();
boolean isSignedRegister = false;
if (registerNum < 0) {
isSignedRegister = true;
registerNum = ~registerNum;
}
processDebugInstruction.ProcessRestartLocal(startDebugOffset, in.getCursor() - startDebugOffset,
registerNum, isSignedRegister);
break;
}
case 0x07:
{
processDebugInstruction.ProcessSetPrologueEnd(startDebugOffset);
break;
}
case 0x08:
{
processDebugInstruction.ProcessSetEpilogueBegin(startDebugOffset);
break;
}
case 0x09:
{
int nameIndex = in.readUnsignedLeb128();
processDebugInstruction.ProcessSetFile(startDebugOffset, in.getCursor() - startDebugOffset,
nameIndex);
break;
}
default:
{
int base = ((debugOpcode & 0xFF) - 0x0A);
processDebugInstruction.ProcessSpecialOpcode(startDebugOffset, debugOpcode, (base % 15) - 4, base / 15);
}
}
}
}
/**
* This method decodes the debug instructions in the given byte array and iterates over them, calling
* the ProcessDebugInstructionDelegate.ProcessDebugInstruction method for each instruction
* @param debugInfoItem the <code>DebugInfoItem</code> to iterate over
* @param registerCount the number of registers in the method that the given debug info is for
* @param processDecodedDebugInstruction a <code>ProcessDebugInstructionDelegate</code> object that gets called
* for each instruction that is encountered
*/
public static void DecodeInstructions(DebugInfoItem debugInfoItem, int registerCount,
ProcessDecodedDebugInstructionDelegate processDecodedDebugInstruction) {
int startDebugOffset;
int currentCodeAddress = 0;
int line = debugInfoItem.getLineStart();
Input in = new ByteArrayInput(debugInfoItem.getEncodedDebugInfo());
DexFile dexFile = debugInfoItem.getDexFile();
Local[] locals = new Local[registerCount];
while(true)
{
startDebugOffset = in.getCursor();
byte debugOpcode = in.readByte();
switch (DebugOpcode.getDebugOpcodeByValue(debugOpcode)) {
case DBG_END_SEQUENCE:
{
return;
}
case DBG_ADVANCE_PC:
{
int codeAddressDiff = in.readUnsignedLeb128();
currentCodeAddress += codeAddressDiff;
break;
}
case DBG_ADVANCE_LINE:
{
int lineDiff = in.readSignedLeb128();
line += lineDiff;
break;
}
case DBG_START_LOCAL:
{
int registerNum = in.readUnsignedLeb128();
StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
TypeIdItem type = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
locals[registerNum] = new Local(registerNum, name, type, null);
processDecodedDebugInstruction.ProcessStartLocal(currentCodeAddress,
in.getCursor() - startDebugOffset, registerNum, name, type);
break;
}
case DBG_START_LOCAL_EXTENDED:
{
int registerNum = in.readUnsignedLeb128();
StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
TypeIdItem type = dexFile.TypeIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
StringIdItem signature =
dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
locals[registerNum] = new Local(registerNum, name, type, signature);
processDecodedDebugInstruction.ProcessStartLocalExtended(currentCodeAddress,
in.getCursor() - startDebugOffset, registerNum, name, type, signature);
break;
}
case DBG_END_LOCAL:
{
int registerNum = in.readUnsignedLeb128();
Local local = locals[registerNum];
if (local == null) {
processDecodedDebugInstruction.ProcessEndLocal(currentCodeAddress, in.getCursor() - startDebugOffset, registerNum,
null, null, null);
} else {
processDecodedDebugInstruction.ProcessEndLocal(currentCodeAddress, in.getCursor() - startDebugOffset, registerNum,
local.name, local.type, local.signature);
}
break;
}
case DBG_RESTART_LOCAL:
{
int registerNum = in.readUnsignedLeb128();
Local local = locals[registerNum];
if (local == null) {
processDecodedDebugInstruction.ProcessRestartLocal(currentCodeAddress, in.getCursor() - startDebugOffset,
registerNum, null, null, null);
} else {
processDecodedDebugInstruction.ProcessRestartLocal(currentCodeAddress, in.getCursor() - startDebugOffset,
registerNum, local.name, local.type, local.signature);
}
break;
}
case DBG_SET_PROLOGUE_END:
{
processDecodedDebugInstruction.ProcessSetPrologueEnd(currentCodeAddress);
break;
}
case DBG_SET_EPILOGUE_BEGIN:
{
processDecodedDebugInstruction.ProcessSetEpilogueBegin(currentCodeAddress);
break;
}
case DBG_SET_FILE:
{
StringIdItem name = dexFile.StringIdsSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
processDecodedDebugInstruction.ProcessSetFile(currentCodeAddress, in.getCursor() - startDebugOffset, name);
break;
}
case DBG_SPECIAL_OPCODE:
{
int base = ((debugOpcode & 0xFF) - 0x0A);
currentCodeAddress += base / 15;
line += (base % 15) - 4;
processDecodedDebugInstruction.ProcessLineEmit(currentCodeAddress, line);
}
}
}
}
public static class ProcessRawDebugInstructionDelegate
{
//TODO: add javadocs
public void ProcessEndSequence(int startDebugOffset) {
ProcessStaticOpcode(DebugOpcode.DBG_END_SEQUENCE, startDebugOffset, 1);
}
public void ProcessAdvancePC(int startDebugOffset, int length, int codeAddressDiff) {
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_PC, startDebugOffset, length);
}
public void ProcessAdvanceLine(int startDebugOffset, int length, int lineDiff) {
ProcessStaticOpcode(DebugOpcode.DBG_ADVANCE_LINE, startDebugOffset, length);
}
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex, int typeIndex,
boolean registerIsSigned) {
}
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex,int signatureIndex, boolean registerIsSigned) {
}
public void ProcessEndLocal(int startDebugOffset, int length, int registerNum, boolean registerIsSigned) {
ProcessStaticOpcode(DebugOpcode.DBG_END_LOCAL, startDebugOffset, length);
}
public void ProcessRestartLocal(int startDebugOffset, int length, int registerNum, boolean registerIsSigned) {
ProcessStaticOpcode(DebugOpcode.DBG_RESTART_LOCAL, startDebugOffset, length);
}
public void ProcessSetPrologueEnd(int startDebugOffset) {
ProcessStaticOpcode(DebugOpcode.DBG_SET_PROLOGUE_END, startDebugOffset, 1);
}
public void ProcessSetEpilogueBegin(int startDebugOffset) {
ProcessStaticOpcode(DebugOpcode.DBG_SET_EPILOGUE_BEGIN, startDebugOffset, 1);
}
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
}
public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDiff, int codeAddressDiff) {
ProcessStaticOpcode(DebugOpcode.DBG_SPECIAL_OPCODE, startDebugOffset, 1);
}
public void ProcessStaticOpcode(DebugOpcode debugOpcode, int startDebugOffset, int length) {
}
}
public static class ProcessDecodedDebugInstructionDelegate
{
public void ProcessStartLocal(int codeAddress, int length, int registerNum, StringIdItem name,
TypeIdItem type) {
}
public void ProcessStartLocalExtended(int codeAddress, int length, int registerNum, StringIdItem name,
TypeIdItem type, StringIdItem signature) {
}
public void ProcessEndLocal(int codeAddress, int length, int registerNum, StringIdItem name, TypeIdItem type,
StringIdItem signature) {
}
public void ProcessRestartLocal(int codeAddress, int length, int registerNum, StringIdItem name,
TypeIdItem type, StringIdItem signature) {
}
public void ProcessSetPrologueEnd(int codeAddress) {
}
public void ProcessSetEpilogueBegin(int codeAddress) {
}
public void ProcessSetFile(int codeAddress, int length, StringIdItem name) {
}
public void ProcessLineEmit(int codeAddress, int line) {
}
}
private static class Local {
public final int register;
public final StringIdItem name;
public final TypeIdItem type;
public final StringIdItem signature;
public Local(int register, StringIdItem name, TypeIdItem type, StringIdItem signature) {
this.register = register;
this.name = name;
this.type = type;
this.signature = signature;
}
}
}

View File

@ -1,64 +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.dexlib.Debug;
public enum DebugOpcode {
DBG_END_SEQUENCE((byte)0x00),
DBG_ADVANCE_PC((byte)0x01),
DBG_ADVANCE_LINE((byte)0x02),
DBG_START_LOCAL((byte)0x03),
DBG_START_LOCAL_EXTENDED((byte)0x04),
DBG_END_LOCAL((byte)0x05),
DBG_RESTART_LOCAL((byte)0x06),
DBG_SET_PROLOGUE_END((byte)0x07),
DBG_SET_EPILOGUE_BEGIN((byte)0x08),
DBG_SET_FILE((byte)0x09),
DBG_SPECIAL_OPCODE((byte)0x0A);
private static DebugOpcode[] opcodesByValue;
static {
opcodesByValue = new DebugOpcode[11];
for (DebugOpcode debugOpcode: DebugOpcode.values()) {
opcodesByValue[debugOpcode.value & 0xFF] = debugOpcode;
}
}
public static DebugOpcode getDebugOpcodeByValue(byte debugOpcodeValue) {
debugOpcodeValue = (byte)Math.min(debugOpcodeValue & 0xFF, 0x0A);
return opcodesByValue[debugOpcodeValue];
}
public final byte value;
DebugOpcode(byte value) {
this.value = value;
}
}

View File

@ -1,620 +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.dexlib;
import org.jf.dexlib.Debug.DebugInstructionIterator;
import org.jf.dexlib.Debug.DebugOpcode;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.ByteArrayInput;
import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.Leb128Utils;
import java.util.ArrayList;
import java.util.List;
public class DebugInfoItem extends Item<DebugInfoItem> {
private int lineStart;
private StringIdItem[] parameterNames;
private byte[] encodedDebugInfo;
private Item[] referencedItems;
private CodeItem parent = null;
/**
* Creates a new uninitialized <code>DebugInfoInfo</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
public DebugInfoItem(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>DebugInfoItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param lineStart the initial value for the line number register for the debug info machine
* @param parameterNames an array of the names of the associated method's parameters. The entire parameter
* can be null if no parameter info is available, or any element can be null to indicate no info for that parameter
* @param encodedDebugInfo the debug info, encoded as a byte array
* @param referencedItems an array of the items referenced by instructions, in order of occurance in the encoded
* debug info
*/
private DebugInfoItem(DexFile dexFile,
int lineStart,
StringIdItem[] parameterNames,
byte[] encodedDebugInfo,
Item[] referencedItems) {
super(dexFile);
this.lineStart = lineStart;
this.parameterNames = parameterNames;
this.encodedDebugInfo = encodedDebugInfo;
this.referencedItems = referencedItems;
}
/**
* Returns a new <code>DebugInfoItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param lineStart the initial value for the line number register for the debug info machine
* @param parameterNames an array of the names of the associated method's parameters. The entire parameter
* can be null if no parameter info is available, or any element can be null to indicate no info for that parameter
* @param encodedDebugInfo the debug info, encoded as a byte array
* @param referencedItems an array of the items referenced by instructions, in order of occurance in the encoded
* debug info
* @return a new <code>DebugInfoItem</code> with the given values
*/
public static DebugInfoItem internDebugInfoItem(DexFile dexFile,
int lineStart,
StringIdItem[] parameterNames,
byte[] encodedDebugInfo,
Item[] referencedItems) {
DebugInfoItem debugInfoItem = new DebugInfoItem(dexFile, lineStart, parameterNames, encodedDebugInfo,
referencedItems);
return dexFile.DebugInfoItemsSection.intern(debugInfoItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
lineStart = in.readUnsignedLeb128();
parameterNames = new StringIdItem[in.readUnsignedLeb128()];
IndexedSection<StringIdItem> stringIdSection = dexFile.StringIdsSection;
for (int i=0; i<parameterNames.length; i++) {
parameterNames[i] = stringIdSection.getOptionalItemByIndex(in.readUnsignedLeb128() - 1);
}
int start = in.getCursor();
final List<Item> referencedItemsList = new ArrayList<Item>(50);
DebugInstructionIterator.IterateInstructions(in,
new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
@Override
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex, boolean registerIsSigned) {
if (nameIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
}
if (typeIndex != -1) {
referencedItemsList.add(dexFile.TypeIdsSection.getItemByIndex(typeIndex));
}
}
@Override
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNume,
int nameIndex, int typeIndex, int signatureIndex,
boolean registerIsSigned) {
if (nameIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
}
if (typeIndex != -1) {
referencedItemsList.add(dexFile.TypeIdsSection.getItemByIndex(typeIndex));
}
if (signatureIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(signatureIndex));
}
}
@Override
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
if (nameIndex != -1) {
referencedItemsList.add(dexFile.StringIdsSection.getItemByIndex(nameIndex));
}
}
});
referencedItems = new Item[referencedItemsList.size()];
referencedItemsList.toArray(referencedItems);
int length = in.getCursor() - start;
in.setCursor(start);
encodedDebugInfo = in.readBytes(length);
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
offset += Leb128Utils.unsignedLeb128Size(lineStart);
offset += Leb128Utils.unsignedLeb128Size(parameterNames.length);
for (StringIdItem parameterName: parameterNames) {
int indexp1;
if (parameterName == null) {
indexp1 = 0;
} else {
indexp1 = parameterName.getIndex() + 1;
}
offset += Leb128Utils.unsignedLeb128Size(indexp1);
}
//make a subclass so we can keep track of and access the computed length
class ProcessDebugInstructionDelegateWithLength extends
DebugInstructionIterator.ProcessRawDebugInstructionDelegate {
public int length = 0;
}
ProcessDebugInstructionDelegateWithLength pdidwl;
//final referencedItems = this.referencedItems;
DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo),
pdidwl = new ProcessDebugInstructionDelegateWithLength() {
private int referencedItemsPosition = 0;
@Override
public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) {
this.length+=length;
}
@Override
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex, boolean registerIsSigned) {
this.length++;
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
this.length += Leb128Utils.signedLeb128Size(registerNum);
} else {
this.length+=Leb128Utils.unsignedLeb128Size(registerNum);
}
if (nameIndex != -1) {
this.length+=
Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1);
} else {
this.length++;
}
if (typeIndex != -1) {
this.length+=
Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1);
} else {
this.length++;
}
}
@Override
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex, int signatureIndex,
boolean registerIsSigned) {
this.length++;
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
this.length += Leb128Utils.signedLeb128Size(registerNum);
} else {
this.length+=Leb128Utils.unsignedLeb128Size(registerNum);
}
if (nameIndex != -1) {
this.length+=
Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1);
} else {
this.length++;
}
if (typeIndex != -1) {
this.length+=
Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1);
} else {
this.length++;
}
if (signatureIndex != -1) {
this.length+=
Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1);
} else {
this.length++;
}
}
@Override
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
this.length++;
if (nameIndex != -1) {
this.length+=
Leb128Utils.unsignedLeb128Size(referencedItems[referencedItemsPosition++].getIndex()+1);
} else {
this.length++;
}
}
});
return offset + pdidwl.length;
}
/** {@inheritDoc} */
protected void writeItem(final AnnotatedOutput out) {
if (out.annotates()) {
writeItemWithAnnotations(out);
} else {
writeItemWithNoAnnotations(out);
}
}
/**
* Replaces the encoded debug info for this DebugInfoItem. It is expected that the new debug info is compatible
* with the existing information, i.e. lineStart, referencedItems, parameterNames
* @param encodedDebugInfo the new encoded debug info
*/
protected void setEncodedDebugInfo(byte[] encodedDebugInfo) {
//TODO: I would rather replace this method with some way of saying "The (code) instruction at address changed from A bytes to B bytes. Fixup the debug info accordingly"
this.encodedDebugInfo = encodedDebugInfo;
}
/**
* Helper method that writes the item, without writing annotations
* @param out the AnnotatedOutput object
*/
private void writeItemWithNoAnnotations(final AnnotatedOutput out) {
out.writeUnsignedLeb128(lineStart);
out.writeUnsignedLeb128(parameterNames.length);
for (StringIdItem parameterName: parameterNames) {
int indexp1;
if (parameterName == null) {
indexp1 = 0;
} else {
indexp1 = parameterName.getIndex() + 1;
}
out.writeUnsignedLeb128(indexp1);
}
DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo),
new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
private int referencedItemsPosition = 0;
@Override
public void ProcessStaticOpcode(DebugOpcode opcode, int startDebugOffset, int length) {
out.write(encodedDebugInfo, startDebugOffset, length);
}
@Override
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex, boolean registerIsSigned) {
out.writeByte(DebugOpcode.DBG_START_LOCAL.value);
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
out.writeSignedLeb128(registerNum);
} else {
out.writeUnsignedLeb128(registerNum);
}
if (nameIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
} else {
out.writeByte(0);
}
if (typeIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
} else {
out.writeByte(0);
}
}
@Override
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex, int signatureIndex,
boolean registerIsSigned) {
out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value);
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
out.writeSignedLeb128(registerNum);
} else {
out.writeUnsignedLeb128(registerNum);
}
if (nameIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
} else {
out.writeByte(0);
}
if (typeIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
} else {
out.writeByte(0);
}
if (signatureIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
} else {
out.writeByte(0);
}
}
@Override
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
out.writeByte(DebugOpcode.DBG_SET_FILE.value);
if (nameIndex != -1) {
out.writeUnsignedLeb128(referencedItems[referencedItemsPosition++].getIndex() + 1);
} else {
out.writeByte(0);
}
}
});
}
/**
* Helper method that writes and annotates the item
* @param out the AnnotatedOutput object
*/
private void writeItemWithAnnotations(final AnnotatedOutput out) {
out.annotate(0, parent.getParent().method.getMethodString());
out.annotate("line_start: 0x" + Integer.toHexString(lineStart) + " (" + lineStart + ")");
out.writeUnsignedLeb128(lineStart);
out.annotate("parameters_size: 0x" + Integer.toHexString(parameterNames.length) + " (" + parameterNames.length
+ ")");
out.writeUnsignedLeb128(parameterNames.length);
int index = 0;
for (StringIdItem parameterName: parameterNames) {
int indexp1;
if (parameterName == null) {
out.annotate("[" + index++ +"] parameterName: ");
indexp1 = 0;
} else {
out.annotate("[" + index++ +"] parameterName: " + parameterName.getStringValue());
indexp1 = parameterName.getIndex() + 1;
}
out.writeUnsignedLeb128(indexp1);
}
DebugInstructionIterator.IterateInstructions(new ByteArrayInput(encodedDebugInfo),
new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
private int referencedItemsPosition = 0;
@Override
public void ProcessEndSequence(int startDebugOffset) {
out.annotate("DBG_END_SEQUENCE");
out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value);
}
@Override
public void ProcessAdvancePC(int startDebugOffset, int length, int addressDiff) {
out.annotate("DBG_ADVANCE_PC");
out.writeByte(DebugOpcode.DBG_ADVANCE_PC.value);
out.indent();
out.annotate("addr_diff: 0x" + Integer.toHexString(addressDiff) + " (" + addressDiff + ")");
out.writeUnsignedLeb128(addressDiff);
out.deindent();
}
@Override
public void ProcessAdvanceLine(int startDebugOffset, int length, int lineDiff) {
out.annotate("DBG_ADVANCE_LINE");
out.writeByte(DebugOpcode.DBG_ADVANCE_LINE.value);
out.indent();
out.annotate("line_diff: 0x" + Integer.toHexString(lineDiff) + " (" + lineDiff + ")");
out.writeSignedLeb128(lineDiff);
out.deindent();
}
@Override
public void ProcessStartLocal(int startDebugOffset, int length, int registerNum, int nameIndex,
int typeIndex, boolean registerIsSigned) {
out.annotate("DBG_START_LOCAL");
out.writeByte(DebugOpcode.DBG_START_LOCAL.value);
out.indent();
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
out.writeSignedLeb128(registerNum);
} else {
out.writeUnsignedLeb128(registerNum);
}
if (nameIndex != -1) {
Item nameItem = referencedItems[referencedItemsPosition++];
assert nameItem instanceof StringIdItem;
out.annotate("name: " + ((StringIdItem)nameItem).getStringValue());
out.writeUnsignedLeb128(nameItem.getIndex() + 1);
} else {
out.annotate("name: ");
out.writeByte(0);
}
if (typeIndex != -1) {
Item typeItem = referencedItems[referencedItemsPosition++];
assert typeItem instanceof TypeIdItem;
out.annotate("type: " + ((TypeIdItem)typeItem).getTypeDescriptor());
out.writeUnsignedLeb128(typeItem.getIndex() + 1);
} else {
out.annotate("type: ");
out.writeByte(0);
}
out.deindent();
}
@Override
public void ProcessStartLocalExtended(int startDebugOffset, int length, int registerNum,
int nameIndex, int typeIndex, int signatureIndex,
boolean registerIsSigned) {
out.annotate("DBG_START_LOCAL_EXTENDED");
out.writeByte(DebugOpcode.DBG_START_LOCAL_EXTENDED.value);
out.indent();
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
if (dexFile.getPreserveSignedRegisters() && registerIsSigned) {
out.writeSignedLeb128(registerNum);
} else {
out.writeUnsignedLeb128(registerNum);
}
if (nameIndex != -1) {
Item nameItem = referencedItems[referencedItemsPosition++];
assert nameItem instanceof StringIdItem;
out.annotate("name: " + ((StringIdItem)nameItem).getStringValue());
out.writeUnsignedLeb128(nameItem.getIndex() + 1);
} else {
out.annotate("name: ");
out.writeByte(0);
}
if (typeIndex != -1) {
Item typeItem = referencedItems[referencedItemsPosition++];
assert typeItem instanceof TypeIdItem;
out.annotate("type: " + ((TypeIdItem)typeItem).getTypeDescriptor());
out.writeUnsignedLeb128(typeItem.getIndex() + 1);
} else {
out.annotate("type: ");
out.writeByte(0);
}
if (signatureIndex != -1) {
Item signatureItem = referencedItems[referencedItemsPosition++];
assert signatureItem instanceof StringIdItem;
out.annotate("signature: " + ((StringIdItem)signatureItem).getStringValue());
out.writeUnsignedLeb128(signatureItem.getIndex() + 1);
} else {
out.annotate("signature: ");
out.writeByte(0);
}
out.deindent();
}
@Override
public void ProcessEndLocal(int startDebugOffset, int length, int registerNum,
boolean registerIsSigned) {
out.annotate("DBG_END_LOCAL");
out.writeByte(DebugOpcode.DBG_END_LOCAL.value);
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
if (registerIsSigned) {
out.writeSignedLeb128(registerNum);
} else {
out.writeUnsignedLeb128(registerNum);
}
}
@Override
public void ProcessRestartLocal(int startDebugOffset, int length, int registerNum,
boolean registerIsSigned) {
out.annotate("DBG_RESTART_LOCAL");
out.writeByte(DebugOpcode.DBG_RESTART_LOCAL.value);
out.annotate("register_num: 0x" + Integer.toHexString(registerNum) + " (" + registerNum + ")");
if (registerIsSigned) {
out.writeSignedLeb128(registerNum);
} else {
out.writeUnsignedLeb128(registerNum);
}
}
@Override
public void ProcessSetPrologueEnd(int startDebugOffset) {
out.annotate("DBG_SET_PROLOGUE_END");
out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value);
}
@Override
public void ProcessSetEpilogueBegin(int startDebugOffset) {
out.annotate("DBG_SET_EPILOGUE_BEGIN");
out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value);
}
@Override
public void ProcessSetFile(int startDebugOffset, int length, int nameIndex) {
out.annotate("DBG_SET_FILE");
out.writeByte(DebugOpcode.DBG_SET_FILE.value);
if (nameIndex != -1) {
Item sourceItem = referencedItems[referencedItemsPosition++];
assert sourceItem instanceof StringIdItem;
out.annotate("source_file: \"" + ((StringIdItem)sourceItem).getStringValue() + "\"");
out.writeUnsignedLeb128(sourceItem.getIndex() + 1);
} else {
out.annotate("source_file: ");
out.writeByte(0);
}
}
@Override
public void ProcessSpecialOpcode(int startDebugOffset, int debugOpcode, int lineDiff,
int addressDiff) {
out.annotate("DBG_SPECIAL_OPCODE: line_diff=0x" + Integer.toHexString(lineDiff) + "(" +
lineDiff +"),addressDiff=0x" + Integer.toHexString(addressDiff) + "(" + addressDiff +
")");
out.writeByte(debugOpcode);
}
});
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_DEBUG_INFO_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
return "debug_info_item @0x" + Integer.toHexString(getOffset());
}
/** {@inheritDoc} */
public int compareTo(DebugInfoItem other) {
if (parent == null) {
if (other.parent == null) {
return 0;
}
return -1;
}
if (other.parent == null) {
return 1;
}
return parent.compareTo(other.parent);
}
/**
* Set the <code>CodeItem</code> that this <code>DebugInfoItem</code> is associated with
* @param codeItem the <code>CodeItem</code> that this <code>DebugInfoItem</code> is associated with
*/
protected void setParent(CodeItem codeItem) {
this.parent = codeItem;
}
/**
* @return the initial value for the line number register for the debug info machine
*/
public int getLineStart() {
return lineStart;
}
/**
* @return the debug info, encoded as a byte array
*/
public byte[] getEncodedDebugInfo() {
return encodedDebugInfo;
}
/**
* @return an array of the items referenced by instructions, in order of occurance in the encoded debug info
*/
public Item[] getReferencedItems() {
return referencedItems;
}
/**
* @return an array of the names of the associated method's parameters. The array can be null if no parameter info
* is available, or any element can be null to indicate no info for that parameter
*/
public StringIdItem[] getParameterNames() {
return parameterNames;
}
}

View File

@ -1,904 +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.dexlib;
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;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.zip.Adler32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* <h3>Main use cases</h3>
*
* <p>These are the main use cases that drove the design of this library</p>
*
* <ol>
* <li><p><b>Annotate an existing dex file</b> - In this case, the intent is to document the structure of
* an existing dex file. We want to be able to read in the dex file, and then write out a dex file
* that is exactly the same (while adding annotation information to an AnnotatedOutput object)</p></li>
*
* <li><p><b>Canonicalize an existing dex file</b> - In this case, the intent is to rewrite an existing dex file
* so that it is in a canonical form. There is a certain amount of leeway in how various types of
* tems in a dex file are ordered or represented. It is sometimes useful to be able to easily
* compare a disassebled and reassembled dex file with the original dex file. If both dex-files are
* written canonically, they "should" match exactly, barring any explicit changes to the reassembled
* file.</p>
*
* <p>Currently, there are a couple of pieces of information that probably won't match exactly
* <ul>
* <li>the order of exception handlers in the <code>EncodedCatchHandlerList</code> for a method</li>
* <li>the ordering of some of the debug info in the <code>{@link org.jf.dexlib.DebugInfoItem}</code> for a method</li>
* </ul></p>
*
*
* <p>Note that the above discrepancies should typically only be "intra-item" differences. They
* shouldn't change the size of the item, or affect how anything else is placed or laid out</p></li>
*
* <li><p><b>Creating a dex file from scratch</b> - In this case, a blank dex file is created and then classes
* are added to it incrementally by calling the {@link org.jf.dexlib.Section#intern intern} method of
* {@link DexFile#ClassDefsSection}, which will add all the information necessary to represent the given
* class. For example, when assembling a dex file from a set of assembly text files.</p>
*
* <p>In this case, we can choose to write the dex file in a canonical form or not. It is somewhat
* slower to write it in a canonical format, due to the extra sorting and calculations that are
* required.</p></li>
*
*
* <li><p><b>Reading in the dex file</b> - In this case, the intent is to read in a dex file and expose all the
* data to the calling application. For example, when disassembling a dex file into a text based
* assembly format, or doing other misc processing of the dex file.</p></li>
*
*
* <h3>Other use cases</h3>
*
* <p>These are other use cases that are possible, but did not drive the design of the library.
* No effort was made to test these use cases or ensure that they work. Some of these could
* probably be better achieved with a disassemble - modify - reassemble type process, using
* smali/baksmali or another assembler/disassembler pair that are compatible with each other</p>
*
* <ul>
* <li>deleting classes/methods/etc. from a dex file</li>
* <li>merging 2 dex files</li>
* <li>splitting a dex file</li>
* <li>moving classes from 1 dex file to another</li>
* <li>removing the debug information from a dex file</li>
* <li>obfustication of a dex file</li>
* </ul>
*/
public class DexFile
{
/**
* A mapping from ItemType to the section that contains items of the given type
*/
private final Section[] sectionsByType;
/**
* Ordered lists of the indexed and offsetted sections. The order of these lists specifies the order
* that the sections will be written in
*/
private final IndexedSection[] indexedSections;
private final OffsettedSection[] offsettedSections;
/**
* dalvik had a bug where it wrote the registers for certain types of debug info in a signed leb
* format, instead of an unsigned leb format. There are no negative registers of course, but
* certain positive values have a different encoding depending on whether they are encoded as
* an unsigned leb128 or a signed leb128. Specifically, the signed leb128 is 1 byte longer in some cases.
*
* This determine whether we should keep any signed registers as signed, or force all register to
* unsigned. By default we don't keep track of whether they were signed or not, and write them back
* out as unsigned. This option only has an effect when reading an existing dex file. It has no
* effect when a dex file is created from scratch
*
* The 2 main use-cases in play are
* 1. Annotate an existing dex file - In this case, preserveSignedRegisters should be false, so that we keep
* track of any signed registers and write them back out as signed Leb128 values.
*
* 2. Canonicalize an existing dex file - In this case, fixRegisters should be true, so that all
* registers in the debug info are written as unsigned Leb128 values regardless of how they were
* originally encoded
*/
private final boolean preserveSignedRegisters;
/**
* When true, any instructions in a code item are skipped over instead of being read in. This is useful when
* you only need the information about the classes and their methods, for example, when loading the BOOTCLASSPATH
* jars in order to analyze a dex file
*/
private final boolean skipInstructions;
/**
* When true, this prevents any sorting of the items during placement of the dex file. This
* should *only* be set to true when this dex file was read in from an existing (valid) dex file,
* and no modifications were made (i.e. no items added or deleted). Otherwise it is likely that
* an invalid dex file will be generated.
*
* This is useful for the first use case (annotating an existing dex file). This ensures the items
* retain the same order as in the original dex file.
*/
private boolean inplace = false;
/**
* When true, this imposes an full ordering on all the items, to force them into a (possibly
* arbitrary) canonical order. When false, only the items that the dex format specifies
* an order for are sorted. The rest of the items are not ordered.
*
* This is useful for the second use case (canonicalizing an existing dex file) or possibly for
* the third use case (creating a dex file from scratch), if there is a need to write the new
* dex file in a canonical form.
*/
private boolean sortAllItems = false;
/**
* Is this file an odex file? This is only set when reading in an odex file
*/
private boolean isOdex = false;
private OdexHeader odexHeader;
private OdexDependencies odexDependencies;
private int dataOffset;
private int dataSize;
private int fileSize;
/**
* A private constructor containing common code to initialize the section maps and lists
* @param preserveSignedRegisters If true, keep track of any registers in the debug information
* @param skipInstructions If true, skip the instructions in any code item.
* that are signed, so they will be written in the same format. See
* <code>getPreserveSignedRegisters()</code>
*/
private DexFile(boolean preserveSignedRegisters, boolean skipInstructions) {
this.preserveSignedRegisters = preserveSignedRegisters;
this.skipInstructions = skipInstructions;
sectionsByType = new Section[] {
StringIdsSection,
TypeIdsSection,
ProtoIdsSection,
FieldIdsSection,
MethodIdsSection,
ClassDefsSection,
TypeListsSection,
AnnotationSetRefListsSection,
AnnotationSetsSection,
ClassDataSection,
CodeItemsSection,
AnnotationDirectoriesSection,
StringDataSection,
DebugInfoItemsSection,
AnnotationsSection,
EncodedArraysSection,
null,
null
};
indexedSections = new IndexedSection[] {
StringIdsSection,
TypeIdsSection,
ProtoIdsSection,
FieldIdsSection,
MethodIdsSection,
ClassDefsSection
};
offsettedSections = new OffsettedSection[] {
AnnotationSetRefListsSection,
AnnotationSetsSection,
CodeItemsSection,
AnnotationDirectoriesSection,
TypeListsSection,
StringDataSection,
AnnotationsSection,
EncodedArraysSection,
ClassDataSection,
DebugInfoItemsSection
};
}
/**
* Construct a new DexFile instance by reading in the given dex file.
* @param file The dex file to read in
* @throws IOException if an IOException occurs
*/
public DexFile(String file)
throws IOException {
this(new File(file), true, false);
}
/**
* Construct a new DexFile instance by reading in the given dex file,
* and optionally keep track of any registers in the debug information that are signed,
* so they will be written in the same format.
* @param file The dex file to read in
* @param preserveSignedRegisters If true, keep track of any registers in the debug information
* that are signed, so they will be written in the same format. See
* @param skipInstructions If true, skip the instructions in any code item.
* <code>getPreserveSignedRegisters()</code>
* @throws IOException if an IOException occurs
*/
public DexFile(String file, boolean preserveSignedRegisters, boolean skipInstructions)
throws IOException {
this(new File(file), preserveSignedRegisters, skipInstructions);
}
/**
* Construct a new DexFile instance by reading in the given dex file.
* @param file The dex file to read in
* @throws IOException if an IOException occurs
*/
public DexFile(File file)
throws IOException {
this(file, true, false);
}
/**
* Construct a new DexFile instance by reading in the given dex file,
* and optionally keep track of any registers in the debug information that are signed,
* so they will be written in the same format.
* @param file The dex file to read in
* @param preserveSignedRegisters If true, keep track of any registers in the debug information
* that are signed, so they will be written in the same format.
* @param skipInstructions If true, skip the instructions in any code item.
* @see #getPreserveSignedRegisters
* @throws IOException if an IOException occurs
*/
public DexFile(File file, boolean preserveSignedRegisters, boolean skipInstructions)
throws IOException {
this(preserveSignedRegisters, skipInstructions);
long fileLength;
byte[] magic = FileUtils.readFile(file, 0, 8);
InputStream inputStream = null;
Input in = null;
ZipFile zipFile = null;
try {
//do we have a zip file?
if (magic[0] == 0x50 && magic[1] == 0x4B) {
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");
}
fileLength = zipEntry.getSize();
if (fileLength < 40) {
throw new RuntimeException("The classes.dex file in " + file.getName() + " is too small to be a" +
" valid dex file");
} else if (fileLength > Integer.MAX_VALUE) {
throw new RuntimeException("The classes.dex file in " + file.getName() + " is too large to read in");
}
inputStream = new BufferedInputStream(zipFile.getInputStream(zipEntry));
inputStream.mark(8);
for (int i=0; i<8; i++) {
magic[i] = (byte)inputStream.read();
}
inputStream.reset();
} else {
fileLength = file.length();
if (fileLength < 40) {
throw new RuntimeException(file.getName() + " is too small to be a valid dex file");
}
if (fileLength < 40) {
throw new RuntimeException(file.getName() + " is too small to be a valid dex file");
} else if (fileLength > Integer.MAX_VALUE) {
throw new RuntimeException(file.getName() + " is too large to read in");
}
inputStream = new FileInputStream(file);
}
byte[] dexMagic, odexMagic;
boolean isDex = false;
this.isOdex = false;
for (int i=0; i<HeaderItem.MAGIC_VALUES.length; i++) {
byte[] magic_value = HeaderItem.MAGIC_VALUES[i];
if (Arrays.equals(magic, magic_value)) {
isDex = true;
break;
}
}
if (!isDex) {
if (Arrays.equals(magic, OdexHeader.MAGIC_35)) {
isOdex = true;
} else if (Arrays.equals(magic, OdexHeader.MAGIC_36)) {
isOdex = true;
}
}
if (isOdex) {
byte[] odexHeaderBytes = FileUtils.readStream(inputStream, 40);
Input odexHeaderIn = new ByteArrayInput(odexHeaderBytes);
odexHeader = new OdexHeader(odexHeaderIn);
int dependencySkip = odexHeader.depsOffset - odexHeader.dexOffset - odexHeader.dexLength;
if (dependencySkip < 0) {
throw new ExceptionWithContext("Unexpected placement of the odex dependency data");
}
if (odexHeader.dexOffset > 40) {
FileUtils.readStream(inputStream, odexHeader.dexOffset - 40);
}
in = new ByteArrayInput(FileUtils.readStream(inputStream, odexHeader.dexLength));
if (dependencySkip > 0) {
FileUtils.readStream(inputStream, dependencySkip);
}
odexDependencies = new OdexDependencies(
new ByteArrayInput(FileUtils.readStream(inputStream, odexHeader.depsLength)));
} else if (isDex) {
in = new ByteArrayInput(FileUtils.readStream(inputStream, (int)fileLength));
} else {
StringBuffer sb = new StringBuffer("bad magic value:");
for (int i=0; i<8; i++) {
sb.append(" ");
sb.append(Hex.u1(magic[i]));
}
throw new RuntimeException(sb.toString());
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (zipFile != null) {
zipFile.close();
}
}
ReadContext readContext = new ReadContext();
HeaderItem.readFrom(in, 0, readContext);
//the map offset was set while reading in the header item
int mapOffset = readContext.getSectionOffset(ItemType.TYPE_MAP_LIST);
in.setCursor(mapOffset);
MapItem.readFrom(in, 0, readContext);
//the sections are ordered in such a way that the item types
Section sections[] = new Section[] {
StringDataSection,
StringIdsSection,
TypeIdsSection,
TypeListsSection,
ProtoIdsSection,
FieldIdsSection,
MethodIdsSection,
AnnotationsSection,
AnnotationSetsSection,
AnnotationSetRefListsSection,
AnnotationDirectoriesSection,
DebugInfoItemsSection,
CodeItemsSection,
ClassDataSection,
EncodedArraysSection,
ClassDefsSection
};
for (Section section: sections) {
if (section == null) {
continue;
}
if (skipInstructions && (section == CodeItemsSection || section == DebugInfoItemsSection)) {
continue;
}
int sectionOffset = readContext.getSectionOffset(section.ItemType);
if (sectionOffset > 0) {
int sectionSize = readContext.getSectionSize(section.ItemType);
in.setCursor(sectionOffset);
section.readFrom(sectionSize, in, readContext);
}
}
}
/**
* Constructs a new, blank dex file. Classes can be added to this dex file by calling
* the <code>Section.intern()</code> method of <code>ClassDefsSection</code>
*/
public DexFile() {
this(true, false);
}
/**
* Get the <code>Section</code> containing items of the same type as the given item
* @param item Get the <code>Section</code> that contains items of this type
* @param <T> The specific item subclass - inferred from the passed item
* @return the <code>Section</code> containing items of the same type as the given item
*/
public <T extends Item> Section<T> getSectionForItem(T item) {
return (Section<T>)sectionsByType[item.getItemType().SectionIndex];
}
/**
* Get the <code>Section</code> containing items of the given type
* @param itemType the type of item
* @return the <code>Section</code> containing items of the given type
*/
public Section getSectionForType(ItemType itemType) {
return sectionsByType[itemType.SectionIndex];
}
/**
* Get a boolean value indicating whether this dex file preserved any signed
* registers in the debug info as it read the dex file in. By default, the dex file
* doesn't check whether the registers are encoded as unsigned or signed values.
*
* This does *not* affect the actual register value that is read in. The value is
* read correctly regardless
*
* This does affect whether any signed registers will retain the same encoding or be
* forced to the (correct) unsigned encoding when the dex file is written back out.
*
* See the discussion about signed register values in the documentation for
* <code>DexFile</code>
* @return a boolean indicating whether this dex file preserved any signed registers
* as it was read in
*/
public boolean getPreserveSignedRegisters() {
return preserveSignedRegisters;
}
/**
* Get a boolean value indicating whether to skip any instructions in a code item while reading in the dex file.
* This is useful when you only need the information about the classes and their methods, for example, when
* loading the BOOTCLASSPATH jars in order to analyze a dex file
* @return a boolean value indicating whether to skip any instructions in a code item
*/
public boolean skipInstructions() {
return skipInstructions;
}
/**
* Get a boolean value indicating whether all items should be placed into a
* (possibly arbitrary) "canonical" ordering. If false, then only the items
* that must be ordered per the dex specification are sorted.
*
* When true, writing the dex file involves somewhat more overhead
*
* If both SortAllItems and Inplace are true, Inplace takes precedence
* @return a boolean value indicating whether all items should be sorted
*/
public boolean getSortAllItems() {
return this.sortAllItems;
}
/**
* Set a boolean value indicating whether all items should be placed into a
* (possibly arbitrary) "canonical" ordering. If false, then only the items
* that must be ordered per the dex specification are sorted.
*
* When true, writing the dex file involves somewhat more overhead
*
* If both SortAllItems and Inplace are true, Inplace takes precedence
* @param value a boolean value indicating whether all items should be sorted
*/
public void setSortAllItems(boolean value) {
this.sortAllItems = value;
}
/**
* @return a boolean value indicating whether this dex file was created by reading in an odex file
*/
public boolean isOdex() {
return this.isOdex;
}
/**
* @return an OdexDependencies object that contains the dependencies for this odex, or null if this
* DexFile represents a dex file instead of an odex file
*/
public OdexDependencies getOdexDependencies() {
return odexDependencies;
}
/**
* @return An OdexHeader object containing the information from the odex header in this dex file, or null if there
* is no odex header
*/
public OdexHeader getOdexHeader() {
return odexHeader;
}
/**
* Get a boolean value indicating whether items in this dex file should be
* written back out "in-place", or whether the normal layout logic should be
* applied.
*
* This should only be used for a dex file that has been read from an existing
* dex file, and no modifications have been made to the dex file. Otherwise,
* there is a good chance that the resulting dex file will be invalid due to
* items that aren't placed correctly
*
* If both SortAllItems and Inplace are true, Inplace takes precedence
* @return a boolean value indicating whether items in this dex file should be
* written back out in-place.
*/
public boolean getInplace() {
return this.inplace;
}
/**
* @return the size of the file, in bytes
*/
public int getFileSize() {
return fileSize;
}
/**
* @return the size of the data section, in bytes
*/
public int getDataSize() {
return dataSize;
}
/**
* @return the offset where the data section begins
*/
public int getDataOffset() {
return dataOffset;
}
/**
* Set a boolean value indicating whether items in this dex file should be
* written back out "in-place", or whether the normal layout logic should be
* applied.
*
* This should only be used for a dex file that has been read from an existing
* dex file, and no modifications have been made to the dex file. Otherwise,
* there is a good chance that the resulting dex file will be invalid due to
* items that aren't placed correctly
*
* If both SortAllItems and Inplace are true, Inplace takes precedence
* @param value a boolean value indicating whether items in this dex file should be
* written back out in-place.
*/
public void setInplace(boolean value) {
this.inplace = value;
}
/**
* Get an array of Section objects that are sorted by offset.
* @return an array of Section objects that are sorted by offset.
*/
protected Section[] getOrderedSections() {
int sectionCount = 0;
for (Section section: sectionsByType) {
if (section != null && section.getItems().size() > 0) {
sectionCount++;
}
}
Section[] sections = new Section[sectionCount];
sectionCount = 0;
for (Section section: sectionsByType) {
if (section != null && section.getItems().size() > 0) {
sections[sectionCount++] = section;
}
}
Arrays.sort(sections, new Comparator<Section>() {
public int compare(Section a, Section b) {
return a.getOffset() - b.getOffset();
}
});
return sections;
}
/**
* This method should be called before writing a dex file. It sorts the sections
* as needed or as indicated by <code>getSortAllItems()</code> and <code>getInplace()</code>,
* and then performs a pass through all of the items, finalizing the position (i.e.
* index and/or offset) of each item in the dex file.
*
* This step is needed primarily so that the indexes and offsets of all indexed and
* offsetted items are available when writing references to those items elsewhere.
*/
public void place() {
int offset = HeaderItem.placeAt(0, 0);
int sectionsPosition = 0;
Section[] sections;
if (this.inplace) {
sections = this.getOrderedSections();
} else {
sections = new Section[indexedSections.length + offsettedSections.length];
System.arraycopy(indexedSections, 0, sections, 0, indexedSections.length);
System.arraycopy(offsettedSections, 0, sections, indexedSections.length, offsettedSections.length);
}
while (sectionsPosition < sections.length && sections[sectionsPosition].ItemType.isIndexedItem()) {
Section section = sections[sectionsPosition];
if (!this.inplace) {
section.sortSection();
}
offset = section.placeAt(offset);
sectionsPosition++;
}
dataOffset = offset;
while (sectionsPosition < sections.length) {
Section section = sections[sectionsPosition];
if (this.sortAllItems && !this.inplace) {
section.sortSection();
}
offset = section.placeAt(offset);
sectionsPosition++;
}
offset = AlignmentUtils.alignOffset(offset, ItemType.TYPE_MAP_LIST.ItemAlignment);
offset = MapItem.placeAt(offset, 0);
fileSize = offset;
dataSize = offset - dataOffset;
}
/**
* Writes the dex file to the give <code>AnnotatedOutput</code> object. If
* <code>out.Annotates()</code> is true, then annotations that document the format
* of the dex file are written.
*
* You must call <code>place()</code> on this dex file, before calling this method
* @param out the AnnotatedOutput object to write the dex file and annotations to
*
* After calling this method, you should call <code>calcSignature()</code> and
* then <code>calcChecksum()</code> on the resulting byte array, to calculate the
* signature and checksum in the header
*/
public void writeTo(AnnotatedOutput out) {
out.annotate(0, "-----------------------------");
out.annotate(0, "header item");
out.annotate(0, "-----------------------------");
out.annotate(0, " ");
HeaderItem.writeTo(out);
out.annotate(0, " ");
int sectionsPosition = 0;
Section[] sections;
if (this.inplace) {
sections = this.getOrderedSections();
} else {
sections = new Section[indexedSections.length + offsettedSections.length];
System.arraycopy(indexedSections, 0, sections, 0, indexedSections.length);
System.arraycopy(offsettedSections, 0, sections, indexedSections.length, offsettedSections.length);
}
while (sectionsPosition < sections.length) {
sections[sectionsPosition].writeTo(out);
sectionsPosition++;
}
out.alignTo(MapItem.getItemType().ItemAlignment);
out.annotate(0, " ");
out.annotate(0, "-----------------------------");
out.annotate(0, "map item");
out.annotate(0, "-----------------------------");
out.annotate(0, " ");
MapItem.writeTo(out);
}
public final HeaderItem HeaderItem = new HeaderItem(this);
public final MapItem MapItem = new MapItem(this);
/**
* The <code>IndexedSection</code> containing <code>StringIdItem</code> items
*/
public final IndexedSection<StringIdItem> StringIdsSection =
new IndexedSection<StringIdItem>(this, ItemType.TYPE_STRING_ID_ITEM);
/**
* The <code>IndexedSection</code> containing <code>TypeIdItem</code> items
*/
public final IndexedSection<TypeIdItem> TypeIdsSection =
new IndexedSection<TypeIdItem>(this, ItemType.TYPE_TYPE_ID_ITEM);
/**
* The <code>IndexedSection</code> containing <code>ProtoIdItem</code> items
*/
public final IndexedSection<ProtoIdItem> ProtoIdsSection =
new IndexedSection<ProtoIdItem>(this, ItemType.TYPE_PROTO_ID_ITEM);
/**
* The <code>IndexedSection</code> containing <code>FieldIdItem</code> items
*/
public final IndexedSection<FieldIdItem> FieldIdsSection =
new IndexedSection<FieldIdItem>(this, ItemType.TYPE_FIELD_ID_ITEM);
/**
* The <code>IndexedSection</code> containing <code>MethodIdItem</code> items
*/
public final IndexedSection<MethodIdItem> MethodIdsSection =
new IndexedSection<MethodIdItem>(this, ItemType.TYPE_METHOD_ID_ITEM);
/**
* The <code>IndexedSection</code> containing <code>ClassDefItem</code> items
*/
public final IndexedSection<ClassDefItem> ClassDefsSection =
new IndexedSection<ClassDefItem>(this, ItemType.TYPE_CLASS_DEF_ITEM) {
public int placeAt(int offset) {
if (DexFile.this.getInplace()) {
return super.placeAt(offset);
}
int ret = ClassDefItem.placeClassDefItems(this, offset);
Collections.sort(this.items);
this.offset = items.get(0).getOffset();
return ret;
}
protected void sortSection() {
// Do nothing. Sorting is handled by ClassDefItem.ClassDefPlacer, during placement
}
};
/**
* The <code>OffsettedSection</code> containing <code>TypeListItem</code> items
*/
public final OffsettedSection<TypeListItem> TypeListsSection =
new OffsettedSection<TypeListItem>(this, ItemType.TYPE_TYPE_LIST);
/**
* The <code>OffsettedSection</code> containing <code>AnnotationSetRefList</code> items
*/
public final OffsettedSection<AnnotationSetRefList> AnnotationSetRefListsSection =
new OffsettedSection<AnnotationSetRefList>(this, ItemType.TYPE_ANNOTATION_SET_REF_LIST);
/**
* The <code>OffsettedSection</code> containing <code>AnnotationSetItem</code> items
*/
public final OffsettedSection<AnnotationSetItem> AnnotationSetsSection =
new OffsettedSection<AnnotationSetItem>(this, ItemType.TYPE_ANNOTATION_SET_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>ClassDataItem</code> items
*/
public final OffsettedSection<ClassDataItem> ClassDataSection =
new OffsettedSection<ClassDataItem>(this, ItemType.TYPE_CLASS_DATA_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>CodeItem</code> items
*/
public final OffsettedSection<CodeItem> CodeItemsSection =
new OffsettedSection<CodeItem>(this, ItemType.TYPE_CODE_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>StringDataItem</code> items
*/
public final OffsettedSection<StringDataItem> StringDataSection =
new OffsettedSection<StringDataItem>(this, ItemType.TYPE_STRING_DATA_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>DebugInfoItem</code> items
*/
public final OffsettedSection<DebugInfoItem> DebugInfoItemsSection =
new OffsettedSection<DebugInfoItem>(this, ItemType.TYPE_DEBUG_INFO_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>AnnotationItem</code> items
*/
public final OffsettedSection<AnnotationItem> AnnotationsSection =
new OffsettedSection<AnnotationItem>(this, ItemType.TYPE_ANNOTATION_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>EncodedArrayItem</code> items
*/
public final OffsettedSection<EncodedArrayItem> EncodedArraysSection =
new OffsettedSection<EncodedArrayItem>(this, ItemType.TYPE_ENCODED_ARRAY_ITEM);
/**
* The <code>OffsettedSection</code> containing <code>AnnotationDirectoryItem</code> items
*/
public final OffsettedSection<AnnotationDirectoryItem> AnnotationDirectoriesSection =
new OffsettedSection<AnnotationDirectoryItem>(this, ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM);
/**
* Calculates the signature for the dex file in the given byte array,
* and then writes the signature to the appropriate location in the header
* containing in the array
*
* @param bytes non-null; the bytes of the file
*/
public static void calcSignature(byte[] bytes) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
md.update(bytes, 32, bytes.length - 32);
try {
int amt = md.digest(bytes, 12, 20);
if (amt != 20) {
throw new RuntimeException("unexpected digest write: " + amt +
" bytes");
}
} catch (DigestException ex) {
throw new RuntimeException(ex);
}
}
/**
* Calculates the checksum for the <code>.dex</code> file in the
* given array, and modify the array to contain it.
*
* @param bytes non-null; the bytes of the file
*/
public static void calcChecksum(byte[] bytes) {
Adler32 a32 = new Adler32();
a32.update(bytes, 12, bytes.length - 12);
int sum = (int) a32.getValue();
bytes[8] = (byte) sum;
bytes[9] = (byte) (sum >> 8);
bytes[10] = (byte) (sum >> 16);
bytes[11] = (byte) (sum >> 24);
}
public static class NoClassesDexException extends ExceptionWithContext {
public NoClassesDexException(String message) {
super(message);
}
}
}

View File

@ -1,135 +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.dexlib;
import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
public class EncodedArrayItem extends Item<EncodedArrayItem> {
private int hashCode = 0;
private ArrayEncodedSubValue encodedArray;
/**
* Creates a new uninitialized <code>EncodedArrayItem</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
*/
protected EncodedArrayItem(DexFile dexFile) {
super(dexFile);
}
/**
* Creates a new <code>EncodedArrayItem</code> with the given values
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param encodedArray The encoded array value
*/
private EncodedArrayItem(DexFile dexFile, ArrayEncodedSubValue encodedArray) {
super(dexFile);
this.encodedArray = encodedArray;
}
/**
* Returns an <code>EncodedArrayItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
* @param dexFile The <code>DexFile</code> that this item belongs to
* @param encodedArray The encoded array value
* @return an <code>EncodedArrayItem</code> for the given values, and that has been interned into the given
*/
public static EncodedArrayItem internEncodedArrayItem(DexFile dexFile, ArrayEncodedSubValue encodedArray) {
EncodedArrayItem encodedArrayItem = new EncodedArrayItem(dexFile, encodedArray);
return dexFile.EncodedArraysSection.intern(encodedArrayItem);
}
/** {@inheritDoc} */
protected void readItem(Input in, ReadContext readContext) {
encodedArray = new ArrayEncodedSubValue(dexFile, in);
}
/** {@inheritDoc} */
protected int placeItem(int offset) {
return encodedArray.placeValue(offset);
}
/** {@inheritDoc} */
protected void writeItem(AnnotatedOutput out) {
encodedArray.writeValue(out);
}
/** {@inheritDoc} */
public ItemType getItemType() {
return ItemType.TYPE_ENCODED_ARRAY_ITEM;
}
/** {@inheritDoc} */
public String getConciseIdentity() {
return "encoded_array @0x" + Integer.toHexString(getOffset());
}
/** {@inheritDoc} */
public int compareTo(EncodedArrayItem encodedArrayItem) {
return encodedArray.compareTo(encodedArrayItem.encodedArray);
}
/**
* @return The encoded array value
*/
public ArrayEncodedSubValue getEncodedArray() {
return encodedArray;
}
/**
* calculate and cache the hashcode
*/
private void calcHashCode() {
hashCode = encodedArray.hashCode();
}
@Override
public int hashCode() {
//there's a small possibility that the actual hash code will be 0. If so, we'll
//just end up recalculating it each time
if (hashCode == 0)
calcHashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (this==o) {
return true;
}
if (o==null || !this.getClass().equals(o.getClass())) {
return false;
}
EncodedArrayItem other = (EncodedArrayItem)o;
return (encodedArray.compareTo(other.encodedArray) == 0);
}
}

View File

@ -1,169 +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.dexlib.EncodedValue;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.StringIdItem;
import org.jf.dexlib.TypeIdItem;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.Leb128Utils;
/**
* An <code>AnnotationEncodedSubValue</code> is identical to an <code>AnnotationEncodedValue</code>, except that it
* doesn't have the initial valueType/valueArg byte. This is used in the <code>AnnotationItem</code> object
*/
public class AnnotationEncodedSubValue extends EncodedValue {
private int hashCode = 0;
public final TypeIdItem annotationType;
public final StringIdItem[] names;
public final EncodedValue[] values;
/**
* Constructs a new <code>AnnotationEncodedSubValue</code> by reading the value from the given <code>Input</code>
* object.
* @param dexFile The <code>DexFile</code> that is being read in
* @param in The <code>Input</code> object to read from
*/
public AnnotationEncodedSubValue(DexFile dexFile, Input in) {
annotationType = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128());
names = new StringIdItem[in.readUnsignedLeb128()];
values = new EncodedValue[names.length];
for (int i=0; i<names.length; i++) {
names[i] = dexFile.StringIdsSection.getItemByIndex(in.readUnsignedLeb128());
values[i] = EncodedValue.readEncodedValue(dexFile, in);
}
}
/**
* Constructs a new <code>AnnotationEncodedValue</code> with the given values. names and values must be the same
* length, and must be sorted according to the name
* @param annotationType The type of the annotation
* @param names An array of the names of the elements of the annotation
* @param values An array of the values of the elements on the annotation
*/
public AnnotationEncodedSubValue(TypeIdItem annotationType, StringIdItem[] names, EncodedValue[] values) {
this.annotationType = annotationType;
if (names.length != values.length) {
throw new RuntimeException("The names and values parameters must be the same length");
}
this.names = names;
this.values = values;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
out.annotate("annotation_type: " + annotationType.getTypeDescriptor());
out.writeUnsignedLeb128(annotationType.getIndex());
out.annotate("element_count: 0x" + Integer.toHexString(names.length) + " (" + names.length + ")");
out.writeUnsignedLeb128(names.length);
for (int i=0; i<names.length; i++) {
out.annotate(0, "[" + i + "] annotation_element");
out.indent();
out.annotate("element_name: " + names[i].getStringValue());
out.writeUnsignedLeb128(names[i].getIndex());
out.annotate(0, "element_value:");
out.indent();
values[i].writeValue(out);
out.deindent();
out.deindent();
}
}
/** {@inheritDoc} */
public int placeValue(int offset) {
offset = offset + Leb128Utils.unsignedLeb128Size(annotationType.getIndex());
offset = offset + Leb128Utils.unsignedLeb128Size(names.length);
for (int i=0; i<names.length; i++) {
offset = offset + Leb128Utils.unsignedLeb128Size(names[i].getIndex());
offset = values[i].placeValue(offset);
}
return offset;
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
AnnotationEncodedSubValue other = (AnnotationEncodedSubValue)o;
int comp = annotationType.compareTo(other.annotationType);
if (comp != 0) {
return comp;
}
comp = names.length - other.names.length;
if (comp != 0) {
return comp;
}
for (int i=0; i<names.length; i++) {
comp = names[i].compareTo(other.names[i]);
if (comp != 0) {
return comp;
}
comp = values[i].compareTo(other.values[i]);
if (comp != 0) {
return comp;
}
}
return comp;
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_ANNOTATION;
}
/**
* calculate and cache the hashcode
*/
private void calcHashCode() {
hashCode = annotationType.hashCode();
for (int i=0; i<names.length; i++) {
hashCode = 31 * hashCode + names[i].hashCode();
hashCode = 31 * hashCode + values[i].hashCode();
}
}
@Override
public int hashCode() {
//there's a small possibility that the actual hash code will be 0. If so, we'll
//just end up recalculating it each time
if (hashCode == 0)
calcHashCode();
return hashCode;
}
}

View File

@ -1,72 +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.dexlib.EncodedValue;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.StringIdItem;
import org.jf.dexlib.TypeIdItem;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
public class AnnotationEncodedValue extends AnnotationEncodedSubValue {
/**
* Constructs a new <code>AnnotationEncodedValue</code> by reading the value from the given <code>Input</code>
* object. The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value
* @param dexFile The <code>DexFile</code> that is being read in
* @param in The <code>Input</code> object to read from
*/
protected AnnotationEncodedValue(DexFile dexFile, Input in) {
super(dexFile, in);
}
/**
* Constructs a new <code>AnnotationEncodedValue</code> with the given values. names and values must be the same
* length, and must be sorted according to the name
* @param annotationType The type of the annotation
* @param names An array of the names of the elements of the annotation
* @param values An array of the values of the elements on the annotation
*/
public AnnotationEncodedValue(TypeIdItem annotationType, StringIdItem[] names, EncodedValue[] values) {
super(annotationType, names, values);
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate("value_type=" + ValueType.VALUE_ANNOTATION.name() + ",value_arg=0");
}
out.writeByte(ValueType.VALUE_ANNOTATION.value);
super.writeValue(out);
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return super.placeValue(offset + 1);
}
}

View File

@ -1,141 +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.dexlib.EncodedValue;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.Leb128Utils;
/**
* An <code>ArrayEncodedSubValue</code> is identical to an <code>ArrayEncodedValue</code>, except that it
* doesn't have the initial valueType/valueArg byte. This is used in the <code>EncodedArrayItem</code> object
*/
public class ArrayEncodedSubValue extends EncodedValue {
private int hashCode = 0;
public final EncodedValue[] values;
/**
* Constructs a new <code>ArrayEncodedSubValue</code> by reading the value from the given <code>Input</code> object.
* The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value
* @param dexFile The <code>DexFile</code> that is being read in
* @param in The <code>Input</code> object to read from
*/
public ArrayEncodedSubValue(DexFile dexFile, Input in) {
values = new EncodedValue[in.readUnsignedLeb128()];
for (int i=0; i<values.length; i++) {
values[i] = EncodedValue.readEncodedValue(dexFile, in);
}
}
/**
* Constructs a new <code>ArrayEncodedSubValue</code> with the given values
* @param values The array values
*/
public ArrayEncodedSubValue(EncodedValue[] values) {
this.values = values;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
if (out.annotates())
{
out.annotate("array_size: 0x" + Integer.toHexString(values.length) + " (" + values.length + ")");
out.writeUnsignedLeb128(values.length);
int index = 0;
for (EncodedValue encodedValue: values) {
out.annotate(0, "[" + index++ + "] array_element");
out.indent();
encodedValue.writeValue(out);
out.deindent();
}
} else {
out.writeUnsignedLeb128(values.length);
for (EncodedValue encodedValue: values) {
encodedValue.writeValue(out);
}
}
}
/** {@inheritDoc} */
public int placeValue(int offset) {
offset = offset + Leb128Utils.unsignedLeb128Size(values.length);
for (EncodedValue encodedValue: values) {
offset = encodedValue.placeValue(offset);
}
return offset;
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
ArrayEncodedSubValue other = (ArrayEncodedSubValue)o;
int comp = values.length - other.values.length;
if (comp != 0) {
return comp;
}
for (int i=0; i<values.length; i++) {
comp = values[i].compareTo(other.values[i]);
if (comp != 0) {
return comp;
}
}
return comp;
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_ARRAY;
}
/**
* calculate and cache the hashcode
*/
private void calcHashCode() {
hashCode = 0;
for (EncodedValue encodedValue: values) {
hashCode = 31 * hashCode + encodedValue.hashCode();
}
}
@Override
public int hashCode() {
//there's a small possibility that the actual hash code will be 0. If so, we'll
//just end up recalculating it each time
if (hashCode == 0)
calcHashCode();
return hashCode;
}
}

View File

@ -1,67 +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.dexlib.EncodedValue;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
public class ArrayEncodedValue extends ArrayEncodedSubValue {
/**
* Constructs a new <code>ArrayEncodedValue</code> by reading the value from the given <code>Input</code> object.
* The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value
* @param dexFile The <code>DexFile</code> that is being read in
* @param in The <code>Input</code> object to read from
*/
protected ArrayEncodedValue(DexFile dexFile, Input in) {
super(dexFile, in);
}
/**
* Constructs a new <code>ArrayEncodedValue</code> with the given values
* @param values The array values
*/
public ArrayEncodedValue(EncodedValue[] values) {
super(values);
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate("value_type=" + ValueType.VALUE_ARRAY.name() + ",value_arg=0");
}
out.writeByte(ValueType.VALUE_ARRAY.value);
super.writeValue(out);
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return super.placeValue(offset + 1);
}
}

View File

@ -1,109 +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.dexlib.EncodedValue;
import org.jf.dexlib.Util.AnnotatedOutput;
public class BooleanEncodedValue extends EncodedValue {
/**
* The dupliton values
*/
public static final BooleanEncodedValue TrueValue = new BooleanEncodedValue(true);
public static final BooleanEncodedValue FalseValue = new BooleanEncodedValue(false);
public final boolean value;
/**
* Constructs a new <code>BooleanEncodedValue</code> with the given value
* @param value The value
*/
private BooleanEncodedValue(boolean value) {
this.value = value;
}
/**
* Gets the <code>BooleanEncodedValue</code> for the given valueArg value. The high 3 bits of the first byte should
* be passed as the valueArg parameter
* @param valueArg The high 3 bits of the first byte of this encoded value
* @return the <code>BooleanEncodedValue</code> for the given valueArg value
*/
protected static BooleanEncodedValue getBooleanEncodedValue(byte valueArg) {
if (valueArg == 0) {
return FalseValue;
} else if (valueArg == 1) {
return TrueValue;
}
throw new RuntimeException("valueArg must be either 0 or 1");
}
/**
* Gets the <code>BooleanEncodedValue</code> for the given boolean value
* @param value the boolean value
* @return the <code>BooleanEncodedValue</code> for the given boolean value
*/
public static BooleanEncodedValue getBooleanEncodedValue(boolean value) {
if (value) {
return TrueValue;
}
return FalseValue;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate("value_type=" + ValueType.VALUE_BOOLEAN.name() + ",value=" + Boolean.toString(value));
}
out.writeByte(ValueType.VALUE_BOOLEAN.value | ((value?1:0) << 5));
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return offset + 1;
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
BooleanEncodedValue other = (BooleanEncodedValue)o;
if (value == other.value)
return 0;
if (value)
return 1;
return -1;
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_BOOLEAN;
}
@Override
public int hashCode() {
return value?1:0;
}
}

View File

@ -1,86 +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.dexlib.EncodedValue;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.EncodedValueUtils;
import org.jf.dexlib.Util.Input;
public class ByteEncodedValue extends EncodedValue {
public final byte value;
/**
* Constructs a new <code>ByteEncodedValue</code> by reading the value from the given <code>Input</code> object.
* The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value
* @param in The <code>Input</code> object to read from
*/
protected ByteEncodedValue(Input in) {
value = (byte)EncodedValueUtils.decodeSignedIntegralValue(in.readBytes(1));
}
/**
* Constructs a new <code>ByteEncodedValue</code> with the given value
* @param value The value
*/
public ByteEncodedValue(byte value) {
this.value = value;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
if (out.annotates()) {
out.annotate(1, "value_type=" + ValueType.VALUE_BYTE.name() + ",value_arg=0");
out.annotate(1, "value: 0x" + Integer.toHexString(value) + " (" + value + ")");
}
out.writeByte(ValueType.VALUE_BYTE.value);
out.writeByte(value);
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return offset + 2;
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
ByteEncodedValue other = (ByteEncodedValue)o;
return (value<other.value?-1:(value>other.value?1:0));
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_BYTE;
}
@Override
public int hashCode() {
return value;
}
}

View File

@ -1,93 +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.dexlib.EncodedValue;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.EncodedValueUtils;
import org.jf.dexlib.Util.Input;
public class CharEncodedValue extends EncodedValue {
public final char value;
/**
* Constructs a new <code>CharEncodedValue</code> by reading the value from the given <code>Input</code> object.
* The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value, and the high 3 bits of
* the first byte should be passed as the valueArg parameter
* @param in The <code>Input</code> object to read from
* @param valueArg The high 3 bits of the first byte of this encoded value
*/
protected CharEncodedValue(Input in, byte valueArg) {
value = (char)EncodedValueUtils.decodeUnsignedIntegralValue(in.readBytes(valueArg+1));
}
/**
* Constructs a new <code>CharEncodedValue</code> with the given value
* @param value The value
*/
public CharEncodedValue(char value) {
this.value = value;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
byte[] bytes = EncodedValueUtils.encodeUnsignedIntegralValue(value);
if (out.annotates()) {
out.annotate(1, "value_type=" + ValueType.VALUE_CHAR.name() + ",value_arg=" + (bytes.length - 1));
char[] c = Character.toChars(value);
assert c.length > 0;
out.annotate(bytes.length, "value: 0x" + Integer.toHexString(value) + " '" + c[0] + "'");
}
out.writeByte(ValueType.VALUE_CHAR.value | ((bytes.length - 1) << 5));
out.write(bytes);
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return offset + EncodedValueUtils.getRequiredBytesForUnsignedIntegralValue(value) + 1;
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
CharEncodedValue other = (CharEncodedValue)o;
return (value<other.value?-1:(value>other.value?1:0));
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_CHAR;
}
@Override
public int hashCode() {
return value;
}
}

View File

@ -1,94 +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.dexlib.EncodedValue;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.EncodedValueUtils;
import org.jf.dexlib.Util.Input;
public class DoubleEncodedValue extends EncodedValue {
public final double value;
/**
* Constructs a new <code>DoubleEncodedValue</code> by reading the value from the given <code>Input</code> object.
* The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value, and the high 3 bits of
* the first byte should be passed as the valueArg parameter
* @param in The <code>Input</code> object to read from
* @param valueArg The high 3 bits of the first byte of this encoded value
*/
protected DoubleEncodedValue(Input in, byte valueArg) {
long longValue = EncodedValueUtils.decodeRightZeroExtendedValue(in.readBytes(valueArg + 1));
value = Double.longBitsToDouble(longValue);
}
/**
* Constructs a new <code>DoubleEncodedValue</code> with the given value
* @param value The value
*/
public DoubleEncodedValue(double value) {
this.value = value;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
byte[] bytes = EncodedValueUtils.encodeRightZeroExtendedValue(Double.doubleToRawLongBits(value));
if (out.annotates()) {
out.annotate(1, "value_type=" + ValueType.VALUE_DOUBLE.name() + ",value_arg=" + (bytes.length - 1));
out.annotate(bytes.length, "value: " + value);
}
out.writeByte(ValueType.VALUE_DOUBLE.value | ((bytes.length - 1) << 5));
out.write(bytes);
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return offset + 1 + EncodedValueUtils.getRequiredBytesForRightZeroExtendedValue(
Double.doubleToRawLongBits(value));
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
DoubleEncodedValue other = (DoubleEncodedValue)o;
return Double.compare(value, other.value);
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_DOUBLE;
}
@Override
public int hashCode() {
return (int)Double.doubleToRawLongBits(value);
}
}

View File

@ -1,125 +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.dexlib.EncodedValue;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input;
public abstract class EncodedValue implements Comparable<EncodedValue> {
/**
* Writes this <code>EncodedValue</code> to the given <code>AnnotatedOutput</code> object
* @param out the <code>AnnotatedOutput</code> object to write to
*/
public abstract void writeValue(AnnotatedOutput out);
/**
* Calculates the size of this encoded value and returns offset + size;
* @param offset The offset to place this encoded value
* @return the offset immediately after this encoded value
*/
public abstract int placeValue(int offset);
public static EncodedValue readEncodedValue(DexFile dexFile, Input in) {
Byte b = in.readByte();
ValueType valueType = ValueType.fromByte((byte)(b & 0x1f));
byte valueArg = (byte)((b & 0xFF) >> 5);
switch (valueType) {
case VALUE_BYTE:
return new ByteEncodedValue(in);
case VALUE_SHORT:
return new ShortEncodedValue(in, valueArg);
case VALUE_CHAR:
return new CharEncodedValue(in, valueArg);
case VALUE_INT:
return new IntEncodedValue(in, valueArg);
case VALUE_LONG:
return new LongEncodedValue(in, valueArg);
case VALUE_FLOAT:
return new FloatEncodedValue(in, valueArg);
case VALUE_DOUBLE:
return new DoubleEncodedValue(in, valueArg);
case VALUE_STRING:
return new StringEncodedValue(dexFile, in, valueArg);
case VALUE_TYPE:
return new TypeEncodedValue(dexFile, in, valueArg);
case VALUE_FIELD:
return new FieldEncodedValue(dexFile, in, valueArg);
case VALUE_METHOD:
return new MethodEncodedValue(dexFile, in, valueArg);
case VALUE_ENUM:
return new EnumEncodedValue(dexFile, in, valueArg);
case VALUE_ARRAY:
return new ArrayEncodedValue(dexFile, in);
case VALUE_ANNOTATION:
return new AnnotationEncodedValue(dexFile, in);
case VALUE_NULL:
return NullEncodedValue.NullValue;
case VALUE_BOOLEAN:
return BooleanEncodedValue.getBooleanEncodedValue(valueArg);
}
return null;
}
/** {@inheritDoc} */
public int compareTo(EncodedValue o) {
int comp = getValueType().compareTo(o.getValueType());
if (comp == 0) {
comp = compareValue(o);
}
return comp;
}
/**
* Compare the value of this <code>EncodedValue</code> against the value of the given <EncodedValue>, which
* is guaranteed to be of the same type as this <code>EncodedValue</code>
* @param o The <code>EncodedValue</code> to compare against
* @return A standard comparison integer value
*/
protected abstract int compareValue(EncodedValue o);
/**
* @return the <code>ValueType</code> representing the type of this <code>EncodedValue</code>
*/
public abstract ValueType getValueType();
@Override
public boolean equals(Object o) {
if (this==o) {
return true;
}
if (o==null || !(o instanceof EncodedValue)) {
return false;
}
return this.compareTo((EncodedValue)o) == 0;
}
}

View File

@ -1,95 +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.dexlib.EncodedValue;
import org.jf.dexlib.DexFile;
import org.jf.dexlib.FieldIdItem;
import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.EncodedValueUtils;
import org.jf.dexlib.Util.Input;
public class EnumEncodedValue extends EncodedValue {
public final FieldIdItem value;
/**
* Constructs a new <code>EnumEncodedValue</code> by reading the field index from the given <code>Input</code>
* object. The <code>Input</code>'s cursor should be set to the 2nd byte of the encoded value, and the high 3 bits
* of the first byte should be passed as the valueArg parameter
* @param dexFile The <code>DexFile</code> that is being read in
* @param in The <code>Input</code> object to read from
* @param valueArg The high 3 bits of the first byte of this encoded value
*/
protected EnumEncodedValue(DexFile dexFile, Input in, byte valueArg) {
int index = (int) EncodedValueUtils.decodeUnsignedIntegralValue(in.readBytes(valueArg+1));
value = dexFile.FieldIdsSection.getItemByIndex(index);
}
/**
* Constructs a new <code>EnumEncodedValue</code> with the given <code>FieldIdItem</code> value
* @param value The <code>FieldIdItem</code> value
*/
public EnumEncodedValue(FieldIdItem value) {
this.value = value;
}
/** {@inheritDoc} */
public void writeValue(AnnotatedOutput out) {
byte[] bytes = EncodedValueUtils.encodeUnsignedIntegralValue(value.getIndex());
if (out.annotates()) {
out.annotate(1, "value_type=" + ValueType.VALUE_ENUM.name() + ",value_arg=" + (bytes.length - 1));
out.annotate(bytes.length, "value: " + value.getFieldString());
}
out.writeByte(ValueType.VALUE_ENUM.value | ((bytes.length - 1) << 5));
out.write(bytes);
}
/** {@inheritDoc} */
public int placeValue(int offset) {
return offset + EncodedValueUtils.getRequiredBytesForUnsignedIntegralValue(value.getIndex()) + 1;
}
/** {@inheritDoc} */
protected int compareValue(EncodedValue o) {
EnumEncodedValue other = (EnumEncodedValue)o;
return value.compareTo(other.value);
}
/** {@inheritDoc} */
public ValueType getValueType() {
return ValueType.VALUE_ENUM;
}
@Override
public int hashCode() {
return value.hashCode();
}
}

Some files were not shown because too many files have changed in this diff Show More