diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java
index 756407b9..a0155e71 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java
@@ -39,7 +39,7 @@ import java.util.List;
import java.util.ArrayList;
public abstract class AnnotationEncodedValueAdaptor {
-
+
public static StringTemplate makeTemplate(StringTemplateGroup stg, AnnotationEncodedSubValue encodedAnnotation) {
StringTemplate template = stg.getInstanceOf("AnnotationEncodedValue");
template.setAttribute("AnnotationType", TypeReference.makeTemplate(stg, encodedAnnotation.annotationType));
diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/EncodedValueAdaptor.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/EncodedValueAdaptor.java
index a54a9bc7..73f0dc56 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/EncodedValueAdaptor.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/EncodedValueAdaptor.java
@@ -58,7 +58,7 @@ public abstract class EncodedValueAdaptor {
return SimpleEncodedValueAdaptor.makeTemplate(stg, ((FloatEncodedValue)encodedValue).value);
case VALUE_INT:
return SimpleEncodedValueAdaptor.makeTemplate(stg, ((IntEncodedValue)encodedValue).value);
- case VALUE_LONG:
+ case VALUE_LONG:
return SimpleEncodedValueAdaptor.makeTemplate(stg, ((LongEncodedValue)encodedValue).value);
case VALUE_METHOD:
return EncodedIndexedItemAdaptor.makeTemplate(stg, MethodReference.makeTemplate(stg,
diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java
index 6e4e6d90..4f2b94bc 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/FieldDefinition.java
@@ -63,13 +63,13 @@ public class FieldDefinition {
fieldTypeDescriptor.length() == 1 ||
initialValue != NullEncodedValue.NullValue
)) {
-
+
template.setAttribute("Comments",
new String[]{"the value of this static final field might be set in the static constructor"});
} else {
template.setAttribute("Comments", null);
}
-
+
if (initialValue != null) {
template.setAttribute("InitialValue", EncodedValueAdaptor.make(stg, initialValue));
}
@@ -96,7 +96,7 @@ public class FieldDefinition {
if (annotationSet == null) {
return null;
}
-
+
List annotationAdaptors = new ArrayList();
for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java
index 43f6a6b2..daec8f3c 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java
@@ -61,7 +61,7 @@ public class MethodDefinition {
template.setAttribute("Annotations", getAnnotations(stg, annotationSet));
template.setAttribute("MethodItems", getMethodItems(encodedMethod.method.getDexFile(), stg, codeItem));
- return template;
+ return template;
}
private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod)
@@ -83,7 +83,7 @@ public class MethodDefinition {
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) {
accessFlags.add(accessFlag.toString());
}
-
+
return accessFlags;
}
@@ -281,7 +281,7 @@ public class MethodDefinition {
}
});
}
-
+
blanks.remove(blanks.size()-1);
addTries();
@@ -334,7 +334,7 @@ public class MethodDefinition {
addInstructionMethodItem(
new Instruction11xMethodItem(codeItem, offset, stg, (Instruction11x)instruction),
commentedOut);
- return;
+ return;
case Format12x:
addInstructionMethodItem(
new Instruction12xMethodItem(codeItem, offset, stg, (Instruction12x)instruction),
diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java
index 9ab0eded..632bef6a 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java
@@ -53,7 +53,7 @@ public class RegisterFormatter {
int registerCount = codeItem.getRegisterCount();
assert startRegister <= lastRegister;
-
+
if (startRegister >= registerCount - parameterRegisterCount) {
return new String[] {"p" + (startRegister - (registerCount - parameterRegisterCount)),
"p" + (lastRegister - (registerCount - parameterRegisterCount))};
diff --git a/baksmali/src/main/java/org/jf/baksmali/Renderers/ByteRenderer.java b/baksmali/src/main/java/org/jf/baksmali/Renderers/ByteRenderer.java
index 0ae16d9a..9b077f64 100644
--- a/baksmali/src/main/java/org/jf/baksmali/Renderers/ByteRenderer.java
+++ b/baksmali/src/main/java/org/jf/baksmali/Renderers/ByteRenderer.java
@@ -42,7 +42,7 @@ public class ByteRenderer implements AttributeRenderer {
public String toString(Object o, String s) {
if (s.equals("unsigned")) {
Byte b = (Byte)o;
- return "0x" + Integer.toHexString(b & 0xFF) + "t";
+ return "0x" + Integer.toHexString(b & 0xFF) + "t";
}
return toString(o);
}
diff --git a/baksmali/src/main/java/org/jf/baksmali/baksmali.java b/baksmali/src/main/java/org/jf/baksmali/baksmali.java
index d70eb9c5..b52e9ba0 100644
--- a/baksmali/src/main/java/org/jf/baksmali/baksmali.java
+++ b/baksmali/src/main/java/org/jf/baksmali/baksmali.java
@@ -57,7 +57,7 @@ public class baksmali {
if (deodexerant != null) {
baksmali.deodexUtil = new DeodexUtil(deodexerant);
}
-
+
File outputDirectoryFile = new File(outputDirectory);
if (!outputDirectoryFile.exists()) {
if (!outputDirectoryFile.mkdirs()) {
@@ -76,7 +76,7 @@ public class baksmali {
templates.registerRenderer(Float.class, new FloatRenderer());
templates.registerRenderer(Character.class, new CharRenderer());
templates.registerRenderer(StringIdItem.class, new StringIdItemRenderer());
-
+
for (ClassDefItem classDefItem: dexFile.ClassDefsSection.getItems()) {
/**
diff --git a/baksmali/src/main/java/org/jf/baksmali/dump.java b/baksmali/src/main/java/org/jf/baksmali/dump.java
index e5158134..ad8d63e3 100644
--- a/baksmali/src/main/java/org/jf/baksmali/dump.java
+++ b/baksmali/src/main/java/org/jf/baksmali/dump.java
@@ -40,7 +40,7 @@ public class dump {
if (sort) {
//sort all items, to guarantee a unique ordering
- dexFile.setSortAllItems(true);
+ dexFile.setSortAllItems(true);
} else {
//don't change the order
dexFile.setInplace(true);
diff --git a/baksmali/src/test/smali/baksmali_test_class.smali b/baksmali/src/test/smali/baksmali_test_class.smali
index 6ae17270..903baf48 100644
--- a/baksmali/src/test/smali/baksmali_test_class.smali
+++ b/baksmali/src/test/smali/baksmali_test_class.smali
@@ -97,7 +97,7 @@
const-string v0, "testing\n123"
goto switch:
-
+
sget v0, Lbaksmali/test/class;->staticField:I
switch:
@@ -194,7 +194,7 @@
.source "somefile.java"
.line 101
-
+
nop
diff --git a/baksmali/src/test/smali/deodex_test1/main.smali b/baksmali/src/test/smali/deodex_test1/main.smali
index 99ffecad..bc6ca320 100644
--- a/baksmali/src/test/smali/deodex_test1/main.smali
+++ b/baksmali/src/test/smali/deodex_test1/main.smali
@@ -28,13 +28,13 @@
invoke-virtual {v0}, Lrandomclass;->getSuperclass()Lsuperclass;
move-result-object v1
-
+
#a branch to outside the dead code. The branch label should not
#be commented out, because there is a non-dead instruction
#that branches to it
if-eqz v0, :here2
-
+
#a branch to inside the dead code. the branch label should be
#commented out
if-eqz v0, :here
@@ -61,14 +61,14 @@
#but still commented out
invoke-virtual {v2}, Lsuperclass;->somemethod()V
-
+
:here2
#and we're back to the non-dead code
invoke-virtual {v2}, Lsuperclass;->somemethod()V
if-nez v0, :here3
-
+
return-void
.end method
diff --git a/baksmali/src/test/smali/deodex_test2/app_classes/main.smali b/baksmali/src/test/smali/deodex_test2/app_classes/main.smali
index 970d4ba0..505312c6 100644
--- a/baksmali/src/test/smali/deodex_test2/app_classes/main.smali
+++ b/baksmali/src/test/smali/deodex_test2/app_classes/main.smali
@@ -6,11 +6,11 @@
.registers 6
const v2, 0
-
-
+
+
const v3, 1
const v4, 0
- new-array v1, v3, [Lsubclass1;
+ new-array v1, v3, [Lsubclass1;
new-instance v0, Lsubclass1;
invoke-direct {v0}, Lsubclass1;->()V
aput-object v0, v1, v4
diff --git a/deodexerant/Main.c b/deodexerant/Main.c
index 4a03bdfc..28aa3547 100644
--- a/deodexerant/Main.c
+++ b/deodexerant/Main.c
@@ -297,17 +297,17 @@ int dumpFields(char *classType, FILE *clientOut)
clazz = dvmFindArrayClass(classType, NULL);
else
clazz = dvmFindSystemClassNoInit(classType);
-
+
if (clazz == NULL)
return 0;
-
+
int i;
do
{
InstField *pField = clazz->ifields;
for (i=0; iifieldCount; i++, pField++)
fprintf(clientOut, "field: %d %s:%s\n", pField->byteOffset, pField->field.name, pField->field.signature);
-
+
clazz = clazz->super;
} while (clazz != NULL);
@@ -318,15 +318,15 @@ int dumpInlineMethods(FILE *clientOut)
{
const InlineOperation *inlineTable = dvmGetInlineOpsTable();
int count = dvmGetInlineOpsTableLength();
-
+
int i;
for (i=0; iclassDescriptor);
if (clazz == NULL)
return 0;
-
+
char *methodType;
Method *method = dvmFindDirectMethodByDescriptor(clazz, inlineOp->methodName, inlineOp->methodSignature);
if (method == NULL)
@@ -339,13 +339,13 @@ int dumpInlineMethods(FILE *clientOut)
else
methodType = "direct";
}
-
+
if (method == NULL)
return 0;
-
+
fprintf(clientOut, "inline: %s %s->%s%s\n", methodType, method->clazz->descriptor, method->name, dexProtoGetMethodDescriptor(&method->prototype, &stringCache));
}
-
+
return 1;
}
@@ -356,14 +356,14 @@ int dumpVirtualMethods(char *classType, FILE *clientOut)
clazz = dvmFindArrayClass(classType, NULL);
else
clazz = dvmFindSystemClassNoInit(classType);
-
-
+
+
if (clazz == NULL)
{
fprintf(clientOut, "err: could not find class %s\n", classType);
return 0;
}
-
+
//interface classes don't have virtual methods, by definition. But it's possible
//to call virtual methods defined on the Object class via an interface type
if (dvmIsInterfaceClass(clazz))
@@ -389,10 +389,10 @@ int dumpVirtualMethods(char *classType, FILE *clientOut)
ClassObject *lookupSuperclass(char *classType)
{
ClassObject *clazz = dvmFindSystemClassNoInit(classType);
-
+
if (clazz == NULL)
return NULL;
-
+
return clazz->super;
}
@@ -428,7 +428,7 @@ int main(int argc, char* const argv[])
fprintf(stderr, "Unable to open '%s': %s\n", inputFileName, strerror(errno));
return 1;
}
-
+
int port = atoi(argv[2]);
int socketFd = socket(AF_INET, SOCK_STREAM, 0);
if (socketFd < 0)
@@ -436,7 +436,7 @@ int main(int argc, char* const argv[])
fprintf(stderr, "Unable to open socket\n");
return 1;
}
-
+
struct sockaddr_in serverAddress, clientAddress;
bzero((char *)&serverAddress, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
@@ -446,14 +446,14 @@ int main(int argc, char* const argv[])
{
fprintf(stderr, "Unable to bind socket\n");
return 1;
- }
+ }
const char* bcp = getenv("BOOTCLASSPATH");
if (bcp == NULL) {
fprintf(stderr, "BOOTCLASSPATH not set\n");
return 1;
}
-
+
DexClassVerifyMode verifyMode = VERIFY_MODE_ALL;
DexOptimizerMode dexOptMode = OPTIMIZE_MODE_VERIFIED;
@@ -498,12 +498,12 @@ int main(int argc, char* const argv[])
fprintf(stderr, "error while loading classes\n");
return 1;
}
-
-
-
-
+
+
+
+
listen(socketFd, 1);
-
+
int clientSocketLength = sizeof(clientAddress);
int clientFd = accept(socketFd, (struct sockaddr *) &clientAddress, &clientSocketLength);
if (clientFd < 0)
@@ -511,14 +511,14 @@ int main(int argc, char* const argv[])
fprintf(stderr, "Unable to accept incomming connection\n");
return 1;
}
-
+
FILE *clientIn = fdopen(clientFd, "r");
if (clientIn == 0)
{
fprintf(stderr, "Unable to fdopen socket to get input stream\n");
return 1;
}
-
+
FILE *clientOut = fdopen(dup(clientFd), "w");
if (clientOut == 0)
{
@@ -536,7 +536,7 @@ int main(int argc, char* const argv[])
char *buf = malloc(len+1);
memcpy(buf, command, len);
buf[len] = 0;
-
+
//printf("%s\n", buf);
char *cmd = strtok(buf, " ");
@@ -557,14 +557,14 @@ int main(int argc, char* const argv[])
fflush(clientOut);
break;
}
-
+
if (!dumpFields(classType, clientOut))
{
fprintf(clientOut, "err: error while dumping fields\n");
fflush(clientOut);
break;
}
-
+
fprintf(clientOut, "done\n");
fflush(clientOut);
break;
@@ -577,7 +577,7 @@ int main(int argc, char* const argv[])
fflush(clientOut);
break;
}
-
+
fprintf(clientOut, "done\n");
fflush(clientOut);
break;
@@ -591,13 +591,13 @@ int main(int argc, char* const argv[])
fflush(clientOut);
break;
}
-
+
if (!dumpVirtualMethods(classType, clientOut)) {
fprintf(clientOut, "err: error encountered while dumping virtual methods\n");
fflush(clientOut);
break;
}
-
+
fprintf(clientOut, "done\n");
fflush(clientOut);
break;
@@ -611,7 +611,7 @@ int main(int argc, char* const argv[])
fflush(clientOut);
break;
}
-
+
ClassObject *clazz = lookupSuperclass(classType);
if (clazz == NULL)
{
@@ -633,20 +633,20 @@ int main(int argc, char* const argv[])
fflush(clientOut);
break;
}
-
+
ClassObject *clazz1;
if (classType1[0] == '[')
clazz1 = dvmFindArrayClass(classType1, NULL);
else
clazz1 = dvmFindSystemClassNoInit(classType1);
-
+
if (clazz1 == NULL)
{
fprintf(clientOut, "err: class %s could not be found for common superclass lookup. This can be caused if a library the odex depends on is not in the BOOTCLASSPATH environment variable\n", classType1);
fflush(clientOut);
break;
- }
-
+ }
+
char *classType2 = strtok(NULL, " ");
if (classType2 == NULL)
{
@@ -654,20 +654,20 @@ int main(int argc, char* const argv[])
fflush(clientOut);
break;
}
-
+
ClassObject *clazz2;
if (classType2[0] == '[')
clazz2 = dvmFindArrayClass(classType2, NULL);
else
clazz2 = dvmFindSystemClassNoInit(classType2);
-
+
if (clazz2 == NULL)
{
fprintf(clientOut, "err: class %s could not be found for common superclass lookup\n", classType2);
fflush(clientOut);
break;
- }
-
+ }
+
ClassObject *clazz = findCommonSuperclass(clazz1, clazz2);
fprintf(clientOut, "class: %s\n", clazz->descriptor);
fflush(clientOut);
@@ -677,12 +677,12 @@ int main(int argc, char* const argv[])
fprintf(clientOut, "err: not a valid command\n");
fflush(clientOut);
}
-
- /*gettimeofday(&tv, NULL);
-
+
+ /*gettimeofday(&tv, NULL);
+
printf("end %07d\n", tv.tv_usec);*/
-
+
}
return 0;
diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java
index c03652aa..38fdbe69 100644
--- a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java
@@ -1,473 +1,473 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-import java.util.Collections;
-import java.util.List;
-
-public class AnnotationDirectoryItem extends Item {
- private AnnotationSetItem classAnnotations;
-
- private FieldIdItem[] fieldAnnotationFields;
- private AnnotationSetItem[] fieldAnnotations;
-
- private MethodIdItem[] methodAnnotationMethods;
- private AnnotationSetItem[] methodAnnotations;
-
- private MethodIdItem[] parameterAnnotationMethods;
- private AnnotationSetRefList[] parameterAnnotations;
-
- /**
- * typically each AnnotationDirectoryItem will have a distinct parent. The only case that isn't true is when
- * the AnnotationDirectoryItem *only* contains class annotations, with no other type of annotation. In that
- * case, the same AnnotationDirectoryItem could be referenced from multiple classes.
- * This isn't a problem though, because this field is only used in compareTo to determine the sort order,
- * which handles it as a special case
- */
- private ClassDefItem parent = null;
-
- /**
- * Creates a new uninitialized AnnotationDirectoryItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected AnnotationDirectoryItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new AnnotationDirectoryItem
with the given values
- * @param dexFile The DexFile
that this item belongs to
- * @param classAnnotations The annotations associated with the overall class
- * @param fieldAnnotationFields An array of FieldIdItem
objects that the annotations in
- * fieldAnnotations
are associated with
- * @param fieldAnnotations An array of AnnotationSetItem
objects that contain the annotations for the
- * fields in fieldAnnotationFields
- * @param methodAnnotationMethods An array of MethodIdItem
objects that the annotations in
- * methodAnnotations
are associated with
- * @param methodAnnotations An array of AnnotationSetItem
objects that contain the annotations for the
- * methods in methodAnnotationMethods
- * @param parameterAnnotationMethods An array of MethodIdItem
objects that the annotations in
- * parameterAnnotations
are associated with
- * @param parameterAnnotations An array of AnnotationSetRefList
objects that contain the parameter
- * annotations for the methods in parameterAnnotationMethods
- */
- private AnnotationDirectoryItem(DexFile dexFile, AnnotationSetItem classAnnotations,
- FieldIdItem[] fieldAnnotationFields, AnnotationSetItem[] fieldAnnotations,
- MethodIdItem[] methodAnnotationMethods, AnnotationSetItem[] methodAnnotations,
- MethodIdItem[] parameterAnnotationMethods,
- AnnotationSetRefList[] parameterAnnotations) {
- super(dexFile);
- this.classAnnotations = classAnnotations;
- this.fieldAnnotationFields = fieldAnnotationFields;
- this.fieldAnnotations = fieldAnnotations;
- this.methodAnnotationMethods = methodAnnotationMethods;
- this.methodAnnotations = methodAnnotations;
- this.parameterAnnotationMethods = parameterAnnotationMethods;
- this.parameterAnnotations = parameterAnnotations;
- }
-
- /**
- * Returns an AnnotationDirectoryItem
for the given values, and that has been interned into the given
- * DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param classAnnotations The annotations associated with the class
- * @param fieldAnnotations A list of FieldAnnotation
objects containing the field annotations
- * @param methodAnnotations A list of MethodAnnotation
objects containing the method annotations
- * @param parameterAnnotations A list of ParameterAnnotation
objects containin the parameter
- * annotations
- * @return an AnnotationItem
for the given values, and that has been interned into the given
- * DexFile
- */
- public static AnnotationDirectoryItem getInternedAnnotationDirectoryItem(DexFile dexFile,
- AnnotationSetItem classAnnotations,
- List fieldAnnotations,
- List methodAnnotations,
- List parameterAnnotations) {
- FieldIdItem[] fieldAnnotationFields = null;
- AnnotationSetItem[] fieldAnnotationsArray = null;
- MethodIdItem[] methodAnnotationMethods = null;
- AnnotationSetItem[] methodAnnotationsArray = null;
- MethodIdItem[] parameterAnnotationMethods = null;
- AnnotationSetRefList[] parameterAnnotationsArray = null;
-
- if (fieldAnnotations != null && fieldAnnotations.size() > 0) {
- fieldAnnotationFields = new FieldIdItem[fieldAnnotations.size()];
- fieldAnnotationsArray = new AnnotationSetItem[fieldAnnotations.size()];
-
- Collections.sort(fieldAnnotations);
-
- int index = 0;
- for (FieldAnnotation fieldAnnotation: fieldAnnotations) {
- fieldAnnotationFields[index] = fieldAnnotation.field;
- fieldAnnotationsArray[index++] = fieldAnnotation.annotationSet;
- }
- }
-
- if (methodAnnotations != null && methodAnnotations.size() > 0) {
- methodAnnotationMethods = new MethodIdItem[methodAnnotations.size()];
- methodAnnotationsArray = new AnnotationSetItem[methodAnnotations.size()];
-
- Collections.sort(methodAnnotations);
-
- int index = 0;
- for (MethodAnnotation methodAnnotation: methodAnnotations) {
- methodAnnotationMethods[index] = methodAnnotation.method;
- methodAnnotationsArray[index++] = methodAnnotation.annotationSet;
- }
- }
-
- if (parameterAnnotations != null && parameterAnnotations.size() > 0) {
- parameterAnnotationMethods = new MethodIdItem[parameterAnnotations.size()];
- parameterAnnotationsArray = new AnnotationSetRefList[parameterAnnotations.size()];
-
- Collections.sort(parameterAnnotations);
-
- int index = 0;
- for (ParameterAnnotation parameterAnnotation: parameterAnnotations) {
- parameterAnnotationMethods[index] = parameterAnnotation.method;
- parameterAnnotationsArray[index++] = parameterAnnotation.annotationSet;
- }
- }
-
- AnnotationDirectoryItem annotationDirectoryItem = new AnnotationDirectoryItem(dexFile, classAnnotations,
- fieldAnnotationFields, fieldAnnotationsArray, methodAnnotationMethods, methodAnnotationsArray,
- parameterAnnotationMethods, parameterAnnotationsArray);
- return dexFile.AnnotationDirectoriesSection.intern(annotationDirectoryItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- classAnnotations = (AnnotationSetItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_SET_ITEM,
- in.readInt());
- fieldAnnotationFields = new FieldIdItem[in.readInt()];
- fieldAnnotations = new AnnotationSetItem[fieldAnnotationFields.length];
-
- methodAnnotationMethods = new MethodIdItem[in.readInt()];
- methodAnnotations = new AnnotationSetItem[methodAnnotationMethods.length];
-
- parameterAnnotationMethods = new MethodIdItem[in.readInt()];
- parameterAnnotations = new AnnotationSetRefList[parameterAnnotationMethods.length];
-
- for (int i=0; iAnnotationDirectoryItem
- */
- public int getFieldAnnotationCount() {
- return fieldAnnotationFields.length;
- }
-
- /**
- * Iterates over the method annotations, calling delegate.processMethodAnnotations for each
- * @param delegate the delegate to call
- */
- public void iterateMethodAnnotations(MethodAnnotationIteratorDelegate delegate) {
- for (int i=0; iAnnotationDirectoryItem
- */
- public int getMethodAnnotationCount() {
- return methodAnnotationMethods.length;
- }
-
- /**
- * Iterates over the parameter annotations, calling delegate.processParameterAnnotations for each
- * @param delegate the delegate to call
- */
- public void iterateParameterAnnotations(ParameterAnnotationIteratorDelegate delegate) {
- for (int i=0; iAnnotationDirectoryItem
- */
- public int getParameterAnnotationCount() {
- return parameterAnnotationMethods.length;
- }
-
- /**
- * @return true if this AnnotationDirectoryItem
is internable. It is only internable if it has
- * only class annotations, but no field, method or parameter annotations
- */
- private boolean isInternable() {
- return classAnnotations != null &&
- (fieldAnnotations == null || fieldAnnotations.length == 0) &&
- (methodAnnotations == null || methodAnnotations.length == 0) &&
- (parameterAnnotations == null || parameterAnnotations.length == 0);
- }
-
- /**
- * Sets the ClassDefItem
that this AnnotationDirectoryItem
is associated with.
- * This is only applicable if this AnnotationDirectoryItem contains only class annotations, and no field, method
- * or parameter annotations.
- * @param classDefItem the ClassDefItem
that this AnnotationDirectoryItem
is associated
- * with
- */
- protected void setParent(ClassDefItem classDefItem) {
- this.parent = classDefItem;
- }
-
- @Override
- public int hashCode() {
- //an instance is only internable if it has only class annotations, but
- //no other type of annotation
- if (!isInternable()) {
- return super.hashCode();
- }
- return classAnnotations.hashCode();
- }
-
- @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 {
- public final FieldIdItem field;
- public final AnnotationSetItem annotationSet;
-
- public FieldAnnotation(FieldIdItem field, AnnotationSetItem annotationSet) {
- this.field = field;
- this.annotationSet = annotationSet;
- }
-
- public int compareTo(FieldAnnotation other) {
- return field.compareTo(other.field);
- }
- }
-
- public static class MethodAnnotation implements Comparable {
- public final MethodIdItem method;
- public final AnnotationSetItem annotationSet;
-
- public MethodAnnotation(MethodIdItem method, AnnotationSetItem annotationSet) {
- this.method = method;
- this.annotationSet = annotationSet;
- }
-
- public int compareTo(MethodAnnotation other) {
- return method.compareTo(other.method);
- }
- }
-
- public static class ParameterAnnotation implements Comparable {
- public final MethodIdItem method;
- public final AnnotationSetRefList annotationSet;
-
- public ParameterAnnotation(MethodIdItem method, AnnotationSetRefList annotationSet) {
- this.method = method;
- this.annotationSet = annotationSet;
- }
-
- public int compareTo(ParameterAnnotation other) {
- return method.compareTo(other.method);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+import java.util.Collections;
+import java.util.List;
+
+public class AnnotationDirectoryItem extends Item {
+ private AnnotationSetItem classAnnotations;
+
+ private FieldIdItem[] fieldAnnotationFields;
+ private AnnotationSetItem[] fieldAnnotations;
+
+ private MethodIdItem[] methodAnnotationMethods;
+ private AnnotationSetItem[] methodAnnotations;
+
+ private MethodIdItem[] parameterAnnotationMethods;
+ private AnnotationSetRefList[] parameterAnnotations;
+
+ /**
+ * typically each AnnotationDirectoryItem will have a distinct parent. The only case that isn't true is when
+ * the AnnotationDirectoryItem *only* contains class annotations, with no other type of annotation. In that
+ * case, the same AnnotationDirectoryItem could be referenced from multiple classes.
+ * This isn't a problem though, because this field is only used in compareTo to determine the sort order,
+ * which handles it as a special case
+ */
+ private ClassDefItem parent = null;
+
+ /**
+ * Creates a new uninitialized AnnotationDirectoryItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected AnnotationDirectoryItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new AnnotationDirectoryItem
with the given values
+ * @param dexFile The DexFile
that this item belongs to
+ * @param classAnnotations The annotations associated with the overall class
+ * @param fieldAnnotationFields An array of FieldIdItem
objects that the annotations in
+ * fieldAnnotations
are associated with
+ * @param fieldAnnotations An array of AnnotationSetItem
objects that contain the annotations for the
+ * fields in fieldAnnotationFields
+ * @param methodAnnotationMethods An array of MethodIdItem
objects that the annotations in
+ * methodAnnotations
are associated with
+ * @param methodAnnotations An array of AnnotationSetItem
objects that contain the annotations for the
+ * methods in methodAnnotationMethods
+ * @param parameterAnnotationMethods An array of MethodIdItem
objects that the annotations in
+ * parameterAnnotations
are associated with
+ * @param parameterAnnotations An array of AnnotationSetRefList
objects that contain the parameter
+ * annotations for the methods in parameterAnnotationMethods
+ */
+ private AnnotationDirectoryItem(DexFile dexFile, AnnotationSetItem classAnnotations,
+ FieldIdItem[] fieldAnnotationFields, AnnotationSetItem[] fieldAnnotations,
+ MethodIdItem[] methodAnnotationMethods, AnnotationSetItem[] methodAnnotations,
+ MethodIdItem[] parameterAnnotationMethods,
+ AnnotationSetRefList[] parameterAnnotations) {
+ super(dexFile);
+ this.classAnnotations = classAnnotations;
+ this.fieldAnnotationFields = fieldAnnotationFields;
+ this.fieldAnnotations = fieldAnnotations;
+ this.methodAnnotationMethods = methodAnnotationMethods;
+ this.methodAnnotations = methodAnnotations;
+ this.parameterAnnotationMethods = parameterAnnotationMethods;
+ this.parameterAnnotations = parameterAnnotations;
+ }
+
+ /**
+ * Returns an AnnotationDirectoryItem
for the given values, and that has been interned into the given
+ * DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param classAnnotations The annotations associated with the class
+ * @param fieldAnnotations A list of FieldAnnotation
objects containing the field annotations
+ * @param methodAnnotations A list of MethodAnnotation
objects containing the method annotations
+ * @param parameterAnnotations A list of ParameterAnnotation
objects containin the parameter
+ * annotations
+ * @return an AnnotationItem
for the given values, and that has been interned into the given
+ * DexFile
+ */
+ public static AnnotationDirectoryItem getInternedAnnotationDirectoryItem(DexFile dexFile,
+ AnnotationSetItem classAnnotations,
+ List fieldAnnotations,
+ List methodAnnotations,
+ List parameterAnnotations) {
+ FieldIdItem[] fieldAnnotationFields = null;
+ AnnotationSetItem[] fieldAnnotationsArray = null;
+ MethodIdItem[] methodAnnotationMethods = null;
+ AnnotationSetItem[] methodAnnotationsArray = null;
+ MethodIdItem[] parameterAnnotationMethods = null;
+ AnnotationSetRefList[] parameterAnnotationsArray = null;
+
+ if (fieldAnnotations != null && fieldAnnotations.size() > 0) {
+ fieldAnnotationFields = new FieldIdItem[fieldAnnotations.size()];
+ fieldAnnotationsArray = new AnnotationSetItem[fieldAnnotations.size()];
+
+ Collections.sort(fieldAnnotations);
+
+ int index = 0;
+ for (FieldAnnotation fieldAnnotation: fieldAnnotations) {
+ fieldAnnotationFields[index] = fieldAnnotation.field;
+ fieldAnnotationsArray[index++] = fieldAnnotation.annotationSet;
+ }
+ }
+
+ if (methodAnnotations != null && methodAnnotations.size() > 0) {
+ methodAnnotationMethods = new MethodIdItem[methodAnnotations.size()];
+ methodAnnotationsArray = new AnnotationSetItem[methodAnnotations.size()];
+
+ Collections.sort(methodAnnotations);
+
+ int index = 0;
+ for (MethodAnnotation methodAnnotation: methodAnnotations) {
+ methodAnnotationMethods[index] = methodAnnotation.method;
+ methodAnnotationsArray[index++] = methodAnnotation.annotationSet;
+ }
+ }
+
+ if (parameterAnnotations != null && parameterAnnotations.size() > 0) {
+ parameterAnnotationMethods = new MethodIdItem[parameterAnnotations.size()];
+ parameterAnnotationsArray = new AnnotationSetRefList[parameterAnnotations.size()];
+
+ Collections.sort(parameterAnnotations);
+
+ int index = 0;
+ for (ParameterAnnotation parameterAnnotation: parameterAnnotations) {
+ parameterAnnotationMethods[index] = parameterAnnotation.method;
+ parameterAnnotationsArray[index++] = parameterAnnotation.annotationSet;
+ }
+ }
+
+ AnnotationDirectoryItem annotationDirectoryItem = new AnnotationDirectoryItem(dexFile, classAnnotations,
+ fieldAnnotationFields, fieldAnnotationsArray, methodAnnotationMethods, methodAnnotationsArray,
+ parameterAnnotationMethods, parameterAnnotationsArray);
+ return dexFile.AnnotationDirectoriesSection.intern(annotationDirectoryItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ classAnnotations = (AnnotationSetItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_SET_ITEM,
+ in.readInt());
+ fieldAnnotationFields = new FieldIdItem[in.readInt()];
+ fieldAnnotations = new AnnotationSetItem[fieldAnnotationFields.length];
+
+ methodAnnotationMethods = new MethodIdItem[in.readInt()];
+ methodAnnotations = new AnnotationSetItem[methodAnnotationMethods.length];
+
+ parameterAnnotationMethods = new MethodIdItem[in.readInt()];
+ parameterAnnotations = new AnnotationSetRefList[parameterAnnotationMethods.length];
+
+ for (int i=0; iAnnotationDirectoryItem
+ */
+ public int getFieldAnnotationCount() {
+ return fieldAnnotationFields.length;
+ }
+
+ /**
+ * Iterates over the method annotations, calling delegate.processMethodAnnotations for each
+ * @param delegate the delegate to call
+ */
+ public void iterateMethodAnnotations(MethodAnnotationIteratorDelegate delegate) {
+ for (int i=0; iAnnotationDirectoryItem
+ */
+ public int getMethodAnnotationCount() {
+ return methodAnnotationMethods.length;
+ }
+
+ /**
+ * Iterates over the parameter annotations, calling delegate.processParameterAnnotations for each
+ * @param delegate the delegate to call
+ */
+ public void iterateParameterAnnotations(ParameterAnnotationIteratorDelegate delegate) {
+ for (int i=0; iAnnotationDirectoryItem
+ */
+ public int getParameterAnnotationCount() {
+ return parameterAnnotationMethods.length;
+ }
+
+ /**
+ * @return true if this AnnotationDirectoryItem
is internable. It is only internable if it has
+ * only class annotations, but no field, method or parameter annotations
+ */
+ private boolean isInternable() {
+ return classAnnotations != null &&
+ (fieldAnnotations == null || fieldAnnotations.length == 0) &&
+ (methodAnnotations == null || methodAnnotations.length == 0) &&
+ (parameterAnnotations == null || parameterAnnotations.length == 0);
+ }
+
+ /**
+ * Sets the ClassDefItem
that this AnnotationDirectoryItem
is associated with.
+ * This is only applicable if this AnnotationDirectoryItem contains only class annotations, and no field, method
+ * or parameter annotations.
+ * @param classDefItem the ClassDefItem
that this AnnotationDirectoryItem
is associated
+ * with
+ */
+ protected void setParent(ClassDefItem classDefItem) {
+ this.parent = classDefItem;
+ }
+
+ @Override
+ public int hashCode() {
+ //an instance is only internable if it has only class annotations, but
+ //no other type of annotation
+ if (!isInternable()) {
+ return super.hashCode();
+ }
+ return classAnnotations.hashCode();
+ }
+
+ @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 {
+ public final FieldIdItem field;
+ public final AnnotationSetItem annotationSet;
+
+ public FieldAnnotation(FieldIdItem field, AnnotationSetItem annotationSet) {
+ this.field = field;
+ this.annotationSet = annotationSet;
+ }
+
+ public int compareTo(FieldAnnotation other) {
+ return field.compareTo(other.field);
+ }
+ }
+
+ public static class MethodAnnotation implements Comparable {
+ public final MethodIdItem method;
+ public final AnnotationSetItem annotationSet;
+
+ public MethodAnnotation(MethodIdItem method, AnnotationSetItem annotationSet) {
+ this.method = method;
+ this.annotationSet = annotationSet;
+ }
+
+ public int compareTo(MethodAnnotation other) {
+ return method.compareTo(other.method);
+ }
+ }
+
+ public static class ParameterAnnotation implements Comparable {
+ public final MethodIdItem method;
+ public final AnnotationSetRefList annotationSet;
+
+ public ParameterAnnotation(MethodIdItem method, AnnotationSetRefList annotationSet) {
+ this.method = method;
+ this.annotationSet = annotationSet;
+ }
+
+ public int compareTo(ParameterAnnotation other) {
+ return method.compareTo(other.method);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationItem.java
index c2b51c89..ec02004e 100644
--- a/dexlib/src/main/java/org/jf/dexlib/AnnotationItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationItem.java
@@ -1,162 +1,162 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.EncodedValue.AnnotationEncodedSubValue;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class AnnotationItem extends Item {
- private int hashCode = 0;
-
- private AnnotationVisibility visibility;
- private AnnotationEncodedSubValue annotationValue;
-
- /**
- * Creates a new uninitialized AnnotationItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected AnnotationItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new AnnotationItem
with the given values
- * @param dexFile The DexFile
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 AnnotationItem
for the given values, and that has been interned into the given
- * DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param visibility The visibility of this annotation
- * @param annotationValue The value of this annotation
- * @return an AnnotationItem
for the given values, and that has been interned into the given
- * DexFile
- */
- public static AnnotationItem getInternedAnnotationItem(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);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.EncodedValue.AnnotationEncodedSubValue;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class AnnotationItem extends Item {
+ private int hashCode = 0;
+
+ private AnnotationVisibility visibility;
+ private AnnotationEncodedSubValue annotationValue;
+
+ /**
+ * Creates a new uninitialized AnnotationItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected AnnotationItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new AnnotationItem
with the given values
+ * @param dexFile The DexFile
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 AnnotationItem
for the given values, and that has been interned into the given
+ * DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param visibility The visibility of this annotation
+ * @param annotationValue The value of this annotation
+ * @return an AnnotationItem
for the given values, and that has been interned into the given
+ * DexFile
+ */
+ public static AnnotationItem getInternedAnnotationItem(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);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java
index 9aabf8be..945bd0cd 100644
--- a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java
@@ -1,169 +1,169 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-import java.util.List;
-
-public class AnnotationSetItem extends Item {
- private int hashCode = 0;
-
- private AnnotationItem[] annotations;
-
- /**
- * Creates a new uninitialized AnnotationSetItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected AnnotationSetItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new AnnotationSetItem
for the given annotations
- * @param dexFile The DexFile
that this item belongs to
- * @param annotations The annotations for this AnnotationSetItem
- */
- private AnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) {
- super(dexFile);
- this.annotations = annotations;
- }
-
- /**
- * Returns an AnnotationSetItem
for the given annotations, and that has been interned into the given
- * DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param annotations The annotations for this AnnotationSetItem
- * @return an AnnotationSetItem
for the given annotations
- */
- public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, List annotations) {
- AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()];
- annotations.toArray(annotationsArray);
- AnnotationSetItem 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; iAnnotationItem objects in this AnnotationSetItem
- */
- 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);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+import java.util.List;
+
+public class AnnotationSetItem extends Item {
+ private int hashCode = 0;
+
+ private AnnotationItem[] annotations;
+
+ /**
+ * Creates a new uninitialized AnnotationSetItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected AnnotationSetItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new AnnotationSetItem
for the given annotations
+ * @param dexFile The DexFile
that this item belongs to
+ * @param annotations The annotations for this AnnotationSetItem
+ */
+ private AnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) {
+ super(dexFile);
+ this.annotations = annotations;
+ }
+
+ /**
+ * Returns an AnnotationSetItem
for the given annotations, and that has been interned into the given
+ * DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param annotations The annotations for this AnnotationSetItem
+ * @return an AnnotationSetItem
for the given annotations
+ */
+ public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, List annotations) {
+ AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()];
+ annotations.toArray(annotationsArray);
+ AnnotationSetItem 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; iAnnotationItem objects in this AnnotationSetItem
+ */
+ 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);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java
index 27a0b1f7..f280d637 100644
--- a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java
+++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java
@@ -1,170 +1,170 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-import java.util.List;
-
-public class AnnotationSetRefList extends Item {
- private int hashCode = 0;
-
- private AnnotationSetItem[] annotationSets;
-
- /**
- * Creates a new uninitialized AnnotationSetRefList
- * @param dexFile The DexFile
that this item belongs to
- */
- protected AnnotationSetRefList(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new AnnotationSetRefList
for the given annotation sets
- * @param dexFile The DexFile
that this item belongs to
- * @param annotationSets The annotationSets for this AnnotationSetRefList
- */
- private AnnotationSetRefList(DexFile dexFile, AnnotationSetItem[] annotationSets) {
- super(dexFile);
- this.annotationSets = annotationSets;
- }
-
- /**
- * Returns an AnnotationSetRefList
for the given annotation sets, and that has been interned into the
- * given DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param annotationSets The annotation sets for this AnnotationSetRefList
- * @return an AnnotationSetItem
for the given annotations
- */
- public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile,
- List 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; iAnnotationSetItem objects that make up this
- * AnnotationSetRefList
- */
- 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);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+import java.util.List;
+
+public class AnnotationSetRefList extends Item {
+ private int hashCode = 0;
+
+ private AnnotationSetItem[] annotationSets;
+
+ /**
+ * Creates a new uninitialized AnnotationSetRefList
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected AnnotationSetRefList(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new AnnotationSetRefList
for the given annotation sets
+ * @param dexFile The DexFile
that this item belongs to
+ * @param annotationSets The annotationSets for this AnnotationSetRefList
+ */
+ private AnnotationSetRefList(DexFile dexFile, AnnotationSetItem[] annotationSets) {
+ super(dexFile);
+ this.annotationSets = annotationSets;
+ }
+
+ /**
+ * Returns an AnnotationSetRefList
for the given annotation sets, and that has been interned into the
+ * given DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param annotationSets The annotation sets for this AnnotationSetRefList
+ * @return an AnnotationSetItem
for the given annotations
+ */
+ public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile,
+ List 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; iAnnotationSetItem objects that make up this
+ * AnnotationSetRefList
+ */
+ 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);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java b/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java
index 11beb268..1ab6b282 100644
--- a/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java
@@ -1,531 +1,531 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.*;
-
-import java.util.List;
-import java.util.Collections;
-
-public class ClassDataItem extends Item {
- private EncodedField[] staticFields;
- private EncodedField[] instanceFields;
- private EncodedMethod[] directMethods;
- private EncodedMethod[] virtualMethods;
-
- private ClassDefItem parent = null;
-
- /**
- * Creates a new uninitialized ClassDataItem
- * @param dexFile The DexFile
that this item belongs to
- */
- public ClassDataItem(final DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new ClassDataItem
with the given values
- * @param dexFile The DexFile
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, EncodedField[] staticFields, EncodedField[] instanceFields,
- EncodedMethod[] directMethods, EncodedMethod[] virtualMethods) {
- super(dexFile);
- this.staticFields = staticFields==null?new EncodedField[0]:staticFields;
- this.instanceFields = instanceFields==null?new EncodedField[0]:instanceFields;
- this.directMethods = directMethods==null?new EncodedMethod[0]:directMethods;
- this.virtualMethods = virtualMethods==null?new EncodedMethod[0]:virtualMethods;
- }
-
- /**
- * Creates a new ClassDataItem
with the given values
- * @param dexFile The DexFile
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 ClassDataItem
with the given values
- */
- public static ClassDataItem getInternedClassDataItem(DexFile dexFile, List staticFields,
- List instanceFields,
- List directMethods,
- List virtualMethods) {
- EncodedField[] staticFieldsArray = null;
- EncodedField[] instanceFieldsArray = null;
- EncodedMethod[] directMethodsArray = null;
- EncodedMethod[] virtualMethodsArray = null;
-
- if (staticFields != null && staticFields.size() > 0) {
- Collections.sort(staticFields);
- staticFieldsArray = new EncodedField[staticFields.size()];
- staticFields.toArray(staticFieldsArray);
- }
-
- if (instanceFields != null && instanceFields.size() > 0) {
- Collections.sort(instanceFields);
- instanceFieldsArray = new EncodedField[instanceFields.size()];
- instanceFields.toArray(instanceFieldsArray);
- }
-
- if (directMethods != null && directMethods.size() > 0) {
- Collections.sort(directMethods);
- directMethodsArray = new EncodedMethod[directMethods.size()];
- directMethods.toArray(directMethodsArray);
- }
-
- if (virtualMethods != null && virtualMethods.size() > 0) {
- Collections.sort(virtualMethods);
- virtualMethodsArray = new EncodedMethod[virtualMethods.size()];
- virtualMethods.toArray(virtualMethodsArray);
- }
-
- ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFieldsArray, instanceFieldsArray,
- directMethodsArray, virtualMethodsArray);
- return dexFile.ClassDataSection.intern(classDataItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- staticFields = new EncodedField[in.readUnsignedLeb128()];
- instanceFields = new EncodedField[in.readUnsignedLeb128()];
- directMethods = new EncodedMethod[in.readUnsignedLeb128()];
- virtualMethods = new EncodedMethod[in.readUnsignedLeb128()];
-
- EncodedField previousEncodedField = null;
- for (int i=0; iClassDefItem that this ClassDataItem
is associated with
- * @param classDefItem the ClassDefItem
that this ClassDataItem
is associated with
- */
- protected void setParent(ClassDefItem classDefItem) {
- this.parent = classDefItem;
- }
-
- /**
- * @return the static fields for this class
- */
- public EncodedField[] getStaticFields() {
- return staticFields;
- }
-
- /**
- * @return the instance fields for this class
- */
- public EncodedField[] getInstanceFields() {
- return instanceFields;
- }
-
- /**
- * @return the direct methods for this class
- */
- public EncodedMethod[] getDirectMethods() {
- return directMethods;
- }
-
- /**
- * @return the virtual methods for this class
- */
- public EncodedMethod[] getVirtualMethods() {
- return virtualMethods;
- }
-
- public static class EncodedField implements Comparable {
- /**
- * The FieldIdItem
that this EncodedField
is associated with
- */
- public final FieldIdItem field;
-
- /**
- * The access flags for this field
- */
- public final int accessFlags;
-
- /**
- * Constructs a new EncodedField
with the given values
- * @param field The FieldIdItem
that this EncodedField
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 EncodedField
while reading in a DexFile
- * @param dexFile The DexFile
that is being read in
- * @param in the Input object to read the EncodedField
from
- * @param previousEncodedField The previous EncodedField
in the list containing this
- * EncodedField
.
- */
- private EncodedField(DexFile dexFile, Input in, EncodedField previousEncodedField) {
- int previousIndex = previousEncodedField==null?0:previousEncodedField.field.getIndex();
- field = dexFile.FieldIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex);
- accessFlags = in.readUnsignedLeb128();
- }
-
- /**
- * Writes the EncodedField
to the given AnnotatedOutput
object
- * @param out the AnnotatedOutput
object to write to
- * @param previousEncodedField The previous EncodedField
in the list containing this
- * EncodedField
.
- */
- 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 EncodedField
and returns the offset
- * immediately following it
- * @param offset the offset of this EncodedField
in the DexFile
- * @param previousEncodedField The previous EncodedField
in the list containing this
- * EncodedField
.
- * @return the offset immediately following this EncodedField
- */
- 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 EncodedField
to another, based on the comparison of the associated
- * FieldIdItem
- * @param other The EncodedField
to compare against
- * @return a standard integer comparison value indicating the relationship
- */
- public int compareTo(EncodedField other)
- {
- return field.compareTo(other.field);
- }
-
- /**
- * @return true if this is a static field
- */
- public boolean isStatic() {
- return (accessFlags & AccessFlags.STATIC.getValue()) != 0;
- }
- }
-
- public static class EncodedMethod implements Comparable {
- /**
- * The MethodIdItem
that this EncodedMethod
is associated with
- */
- public final MethodIdItem method;
-
- /**
- * The access flags for this method
- */
- public final int accessFlags;
-
- /**
- * The CodeItem
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 EncodedMethod
with the given values
- * @param method The MethodIdItem
that this EncodedMethod
is associated with
- * @param accessFlags The access flags for this method
- * @param codeItem The CodeItem
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 EncodedMethod
while reading in a DexFile
- * @param dexFile The DexFile
that is being read in
- * @param readContext a ReadContext
object to hold information that is only needed while reading
- * in a file
- * @param in the Input object to read the EncodedMethod
from
- * @param previousEncodedMethod The previous EncodedMethod
in the list containing this
- * EncodedMethod
.
- */
- 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();
- codeItem = (CodeItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CODE_ITEM, in.readUnsignedLeb128());
- if (codeItem != null) {
- codeItem.setParent(this);
- }
- }
-
- /**
- * Writes the EncodedMethod
to the given AnnotatedOutput
object
- * @param out the AnnotatedOutput
object to write to
- * @param previousEncodedMethod The previous EncodedMethod
in the list containing this
- * EncodedMethod
.
- */
- 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" + 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 EncodedMethod
and returns the offset
- * immediately following it
- * @param offset the offset of this EncodedMethod
in the DexFile
- * @param previousEncodedMethod The previous EncodedMethod
in the list containing this
- * EncodedMethod
.
- * @return the offset immediately following this EncodedField
- */
- 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 EncodedMethod
to another, based on the comparison of the associated
- * MethodIdItem
- * @param other The EncodedMethod
to compare against
- * @return a standard integer comparison value indicating the relationship
- */
- public int compareTo(EncodedMethod other) {
- return method.compareTo(other.method);
- }
-
- /**
- * @return true if this is a direct method
- */
- public boolean isDirect() {
- return ((accessFlags & (AccessFlags.STATIC.getValue() | AccessFlags.PRIVATE.getValue() |
- AccessFlags.CONSTRUCTOR.getValue())) != 0);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.*;
+
+import java.util.List;
+import java.util.Collections;
+
+public class ClassDataItem extends Item {
+ private EncodedField[] staticFields;
+ private EncodedField[] instanceFields;
+ private EncodedMethod[] directMethods;
+ private EncodedMethod[] virtualMethods;
+
+ private ClassDefItem parent = null;
+
+ /**
+ * Creates a new uninitialized ClassDataItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ public ClassDataItem(final DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new ClassDataItem
with the given values
+ * @param dexFile The DexFile
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, EncodedField[] staticFields, EncodedField[] instanceFields,
+ EncodedMethod[] directMethods, EncodedMethod[] virtualMethods) {
+ super(dexFile);
+ this.staticFields = staticFields==null?new EncodedField[0]:staticFields;
+ this.instanceFields = instanceFields==null?new EncodedField[0]:instanceFields;
+ this.directMethods = directMethods==null?new EncodedMethod[0]:directMethods;
+ this.virtualMethods = virtualMethods==null?new EncodedMethod[0]:virtualMethods;
+ }
+
+ /**
+ * Creates a new ClassDataItem
with the given values
+ * @param dexFile The DexFile
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 ClassDataItem
with the given values
+ */
+ public static ClassDataItem getInternedClassDataItem(DexFile dexFile, List staticFields,
+ List instanceFields,
+ List directMethods,
+ List virtualMethods) {
+ EncodedField[] staticFieldsArray = null;
+ EncodedField[] instanceFieldsArray = null;
+ EncodedMethod[] directMethodsArray = null;
+ EncodedMethod[] virtualMethodsArray = null;
+
+ if (staticFields != null && staticFields.size() > 0) {
+ Collections.sort(staticFields);
+ staticFieldsArray = new EncodedField[staticFields.size()];
+ staticFields.toArray(staticFieldsArray);
+ }
+
+ if (instanceFields != null && instanceFields.size() > 0) {
+ Collections.sort(instanceFields);
+ instanceFieldsArray = new EncodedField[instanceFields.size()];
+ instanceFields.toArray(instanceFieldsArray);
+ }
+
+ if (directMethods != null && directMethods.size() > 0) {
+ Collections.sort(directMethods);
+ directMethodsArray = new EncodedMethod[directMethods.size()];
+ directMethods.toArray(directMethodsArray);
+ }
+
+ if (virtualMethods != null && virtualMethods.size() > 0) {
+ Collections.sort(virtualMethods);
+ virtualMethodsArray = new EncodedMethod[virtualMethods.size()];
+ virtualMethods.toArray(virtualMethodsArray);
+ }
+
+ ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFieldsArray, instanceFieldsArray,
+ directMethodsArray, virtualMethodsArray);
+ return dexFile.ClassDataSection.intern(classDataItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ staticFields = new EncodedField[in.readUnsignedLeb128()];
+ instanceFields = new EncodedField[in.readUnsignedLeb128()];
+ directMethods = new EncodedMethod[in.readUnsignedLeb128()];
+ virtualMethods = new EncodedMethod[in.readUnsignedLeb128()];
+
+ EncodedField previousEncodedField = null;
+ for (int i=0; iClassDefItem that this ClassDataItem
is associated with
+ * @param classDefItem the ClassDefItem
that this ClassDataItem
is associated with
+ */
+ protected void setParent(ClassDefItem classDefItem) {
+ this.parent = classDefItem;
+ }
+
+ /**
+ * @return the static fields for this class
+ */
+ public EncodedField[] getStaticFields() {
+ return staticFields;
+ }
+
+ /**
+ * @return the instance fields for this class
+ */
+ public EncodedField[] getInstanceFields() {
+ return instanceFields;
+ }
+
+ /**
+ * @return the direct methods for this class
+ */
+ public EncodedMethod[] getDirectMethods() {
+ return directMethods;
+ }
+
+ /**
+ * @return the virtual methods for this class
+ */
+ public EncodedMethod[] getVirtualMethods() {
+ return virtualMethods;
+ }
+
+ public static class EncodedField implements Comparable {
+ /**
+ * The FieldIdItem
that this EncodedField
is associated with
+ */
+ public final FieldIdItem field;
+
+ /**
+ * The access flags for this field
+ */
+ public final int accessFlags;
+
+ /**
+ * Constructs a new EncodedField
with the given values
+ * @param field The FieldIdItem
that this EncodedField
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 EncodedField
while reading in a DexFile
+ * @param dexFile The DexFile
that is being read in
+ * @param in the Input object to read the EncodedField
from
+ * @param previousEncodedField The previous EncodedField
in the list containing this
+ * EncodedField
.
+ */
+ private EncodedField(DexFile dexFile, Input in, EncodedField previousEncodedField) {
+ int previousIndex = previousEncodedField==null?0:previousEncodedField.field.getIndex();
+ field = dexFile.FieldIdsSection.getItemByIndex(in.readUnsignedLeb128() + previousIndex);
+ accessFlags = in.readUnsignedLeb128();
+ }
+
+ /**
+ * Writes the EncodedField
to the given AnnotatedOutput
object
+ * @param out the AnnotatedOutput
object to write to
+ * @param previousEncodedField The previous EncodedField
in the list containing this
+ * EncodedField
.
+ */
+ 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 EncodedField
and returns the offset
+ * immediately following it
+ * @param offset the offset of this EncodedField
in the DexFile
+ * @param previousEncodedField The previous EncodedField
in the list containing this
+ * EncodedField
.
+ * @return the offset immediately following this EncodedField
+ */
+ 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 EncodedField
to another, based on the comparison of the associated
+ * FieldIdItem
+ * @param other The EncodedField
to compare against
+ * @return a standard integer comparison value indicating the relationship
+ */
+ public int compareTo(EncodedField other)
+ {
+ return field.compareTo(other.field);
+ }
+
+ /**
+ * @return true if this is a static field
+ */
+ public boolean isStatic() {
+ return (accessFlags & AccessFlags.STATIC.getValue()) != 0;
+ }
+ }
+
+ public static class EncodedMethod implements Comparable {
+ /**
+ * The MethodIdItem
that this EncodedMethod
is associated with
+ */
+ public final MethodIdItem method;
+
+ /**
+ * The access flags for this method
+ */
+ public final int accessFlags;
+
+ /**
+ * The CodeItem
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 EncodedMethod
with the given values
+ * @param method The MethodIdItem
that this EncodedMethod
is associated with
+ * @param accessFlags The access flags for this method
+ * @param codeItem The CodeItem
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 EncodedMethod
while reading in a DexFile
+ * @param dexFile The DexFile
that is being read in
+ * @param readContext a ReadContext
object to hold information that is only needed while reading
+ * in a file
+ * @param in the Input object to read the EncodedMethod
from
+ * @param previousEncodedMethod The previous EncodedMethod
in the list containing this
+ * EncodedMethod
.
+ */
+ 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();
+ codeItem = (CodeItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CODE_ITEM, in.readUnsignedLeb128());
+ if (codeItem != null) {
+ codeItem.setParent(this);
+ }
+ }
+
+ /**
+ * Writes the EncodedMethod
to the given AnnotatedOutput
object
+ * @param out the AnnotatedOutput
object to write to
+ * @param previousEncodedMethod The previous EncodedMethod
in the list containing this
+ * EncodedMethod
.
+ */
+ 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" + 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 EncodedMethod
and returns the offset
+ * immediately following it
+ * @param offset the offset of this EncodedMethod
in the DexFile
+ * @param previousEncodedMethod The previous EncodedMethod
in the list containing this
+ * EncodedMethod
.
+ * @return the offset immediately following this EncodedField
+ */
+ 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 EncodedMethod
to another, based on the comparison of the associated
+ * MethodIdItem
+ * @param other The EncodedMethod
to compare against
+ * @return a standard integer comparison value indicating the relationship
+ */
+ public int compareTo(EncodedMethod other) {
+ return method.compareTo(other.method);
+ }
+
+ /**
+ * @return true if this is a direct method
+ */
+ public boolean isDirect() {
+ return ((accessFlags & (AccessFlags.STATIC.getValue() | AccessFlags.PRIVATE.getValue() |
+ AccessFlags.CONSTRUCTOR.getValue())) != 0);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java b/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java
index b15b6663..34e27b37 100644
--- a/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java
@@ -1,377 +1,377 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.AccessFlags;
-import org.jf.dexlib.Util.TypeUtils;
-import org.jf.dexlib.EncodedValue.EncodedValue;
-import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
-
-import java.util.*;
-
-public class ClassDefItem extends Item {
- private TypeIdItem classType;
- private int accessFlags;
- private TypeIdItem superType;
- private TypeListItem implementedInterfaces;
- private StringIdItem sourceFile;
- private AnnotationDirectoryItem annotations;
- private ClassDataItem classData;
- private EncodedArrayItem staticFieldInitializers;
-
- /**
- * Creates a new uninitialized ClassDefItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected ClassDefItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new ClassDefItem
with the given values
- * @param dexFile The DexFile
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 ClassDataItem
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 ClassDataItem
. 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, TypeIdItem superType,
- TypeListItem implementedInterfaces, StringIdItem sourceFile,
- AnnotationDirectoryItem annotations, ClassDataItem classData,
- EncodedArrayItem staticFieldInitializers) {
- super(dexFile);
- this.classType = classType;
- this.accessFlags = accessFlags;
- this.superType = superType;
- this.implementedInterfaces = implementedInterfaces;
- this.sourceFile = sourceFile;
- this.annotations = annotations;
- this.classData = classData;
- this.staticFieldInitializers = staticFieldInitializers;
-
- if (classData != null) {
- classData.setParent(this);
- }
- if (annotations != null) {
- annotations.setParent(this);
- }
- }
-
- /**
- * Returns a ClassDefItem
for the given values, and that has been interned into the given
- * DexFile
- * @param dexFile The DexFile
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 ClassDataItem
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
- * StaticFieldInitializer
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 ClassDefItem
for the given values, and that has been interned into the given
- * DexFile
- */
- public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags,
- TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile,
- AnnotationDirectoryItem annotations, ClassDataItem classData,
- List staticFieldInitializers) {
- EncodedArrayItem encodedArrayItem = null;
- if(!dexFile.getInplace() && staticFieldInitializers != null && staticFieldInitializers.size() > 0) {
- assert classData != null;
- assert staticFieldInitializers.size() == classData.getStaticFields().length;
- 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.getItemByIndex(in.readInt());
- implementedInterfaces = (TypeListItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST,
- in.readInt());
- sourceFile = dexFile.StringIdsSection.getItemByIndex(in.readInt());
- annotations = (AnnotationDirectoryItem)readContext.getOffsettedItemByOffset(
- ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, in.readInt());
- classData = (ClassDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
- staticFieldInitializers = (EncodedArrayItem)readContext.getOffsettedItemByOffset(
- ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
-
- if (classData != null) {
- classData.setParent(this);
- }
- if (annotations != null) {
- annotations.setParent(this);
- }
- }
-
- /** {@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 implemented in SortClassDefItemSection.
- //This method is just used for sorting the associated ClassDataItem items, so
- //we can just do the comparison based on the offsets of the items
- return this.getOffset() - o.getOffset();
- }
-
- public TypeIdItem getClassType() {
- return classType;
- }
-
- public int getAccessFlags() {
- return accessFlags;
- }
-
- public TypeIdItem getSuperclass() {
- return superType;
- }
-
- public TypeListItem getInterfaces() {
- return implementedInterfaces;
- }
-
- public StringIdItem getSourceFile() {
- return sourceFile;
- }
-
- public AnnotationDirectoryItem getAnnotations() {
- return annotations;
- }
-
- public ClassDataItem getClassData() {
- return classData;
- }
-
- public EncodedArrayItem getStaticFieldInitializers() {
- return staticFieldInitializers;
- }
-
- public static int placeClassDefItems(IndexedSection 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 section;
- private final HashMap unplacedClassDefsByType =
- new HashMap();
-
- private int currentIndex = 0;
- private int currentOffset;
-
- public ClassDefPlacer(IndexedSection 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() {
- 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.getOffset() == -1) {
- 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 {
- 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 DexFile
- * @param staticFieldInitializers the initial values
- * @return an interned EncodedArrayItem containing the static field initializers
- */
- private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
- List staticFieldInitializers) {
- if (staticFieldInitializers == null || staticFieldInitializers.size() == 0) {
- return null;
- }
-
- int len = staticFieldInitializers.size();
-
- 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(dexFile,
- staticFieldInitializer.field.field.getFieldType().getTypeDescriptor())) != 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(dexFile,
- staticFieldInitializer.field.field.getFieldType().getTypeDescriptor());
- }
-
- values[i] = encodedValue;
- }
-
- ArrayEncodedSubValue encodedArrayValue = new ArrayEncodedSubValue(values);
- return EncodedArrayItem.getInternedEncodedArrayItem(dexFile, encodedArrayValue);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+import org.jf.dexlib.Util.AccessFlags;
+import org.jf.dexlib.Util.TypeUtils;
+import org.jf.dexlib.EncodedValue.EncodedValue;
+import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
+
+import java.util.*;
+
+public class ClassDefItem extends Item {
+ private TypeIdItem classType;
+ private int accessFlags;
+ private TypeIdItem superType;
+ private TypeListItem implementedInterfaces;
+ private StringIdItem sourceFile;
+ private AnnotationDirectoryItem annotations;
+ private ClassDataItem classData;
+ private EncodedArrayItem staticFieldInitializers;
+
+ /**
+ * Creates a new uninitialized ClassDefItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected ClassDefItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new ClassDefItem
with the given values
+ * @param dexFile The DexFile
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 ClassDataItem
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 ClassDataItem
. 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, TypeIdItem superType,
+ TypeListItem implementedInterfaces, StringIdItem sourceFile,
+ AnnotationDirectoryItem annotations, ClassDataItem classData,
+ EncodedArrayItem staticFieldInitializers) {
+ super(dexFile);
+ this.classType = classType;
+ this.accessFlags = accessFlags;
+ this.superType = superType;
+ this.implementedInterfaces = implementedInterfaces;
+ this.sourceFile = sourceFile;
+ this.annotations = annotations;
+ this.classData = classData;
+ this.staticFieldInitializers = staticFieldInitializers;
+
+ if (classData != null) {
+ classData.setParent(this);
+ }
+ if (annotations != null) {
+ annotations.setParent(this);
+ }
+ }
+
+ /**
+ * Returns a ClassDefItem
for the given values, and that has been interned into the given
+ * DexFile
+ * @param dexFile The DexFile
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 ClassDataItem
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
+ * StaticFieldInitializer
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 ClassDefItem
for the given values, and that has been interned into the given
+ * DexFile
+ */
+ public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags,
+ TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile,
+ AnnotationDirectoryItem annotations, ClassDataItem classData,
+ List staticFieldInitializers) {
+ EncodedArrayItem encodedArrayItem = null;
+ if(!dexFile.getInplace() && staticFieldInitializers != null && staticFieldInitializers.size() > 0) {
+ assert classData != null;
+ assert staticFieldInitializers.size() == classData.getStaticFields().length;
+ 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.getItemByIndex(in.readInt());
+ implementedInterfaces = (TypeListItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST,
+ in.readInt());
+ sourceFile = dexFile.StringIdsSection.getItemByIndex(in.readInt());
+ annotations = (AnnotationDirectoryItem)readContext.getOffsettedItemByOffset(
+ ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM, in.readInt());
+ classData = (ClassDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
+ staticFieldInitializers = (EncodedArrayItem)readContext.getOffsettedItemByOffset(
+ ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
+
+ if (classData != null) {
+ classData.setParent(this);
+ }
+ if (annotations != null) {
+ annotations.setParent(this);
+ }
+ }
+
+ /** {@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 implemented in SortClassDefItemSection.
+ //This method is just used for sorting the associated ClassDataItem items, so
+ //we can just do the comparison based on the offsets of the items
+ return this.getOffset() - o.getOffset();
+ }
+
+ public TypeIdItem getClassType() {
+ return classType;
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ public TypeIdItem getSuperclass() {
+ return superType;
+ }
+
+ public TypeListItem getInterfaces() {
+ return implementedInterfaces;
+ }
+
+ public StringIdItem getSourceFile() {
+ return sourceFile;
+ }
+
+ public AnnotationDirectoryItem getAnnotations() {
+ return annotations;
+ }
+
+ public ClassDataItem getClassData() {
+ return classData;
+ }
+
+ public EncodedArrayItem getStaticFieldInitializers() {
+ return staticFieldInitializers;
+ }
+
+ public static int placeClassDefItems(IndexedSection 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 section;
+ private final HashMap unplacedClassDefsByType =
+ new HashMap();
+
+ private int currentIndex = 0;
+ private int currentOffset;
+
+ public ClassDefPlacer(IndexedSection 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() {
+ 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.getOffset() == -1) {
+ 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 {
+ 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 DexFile
+ * @param staticFieldInitializers the initial values
+ * @return an interned EncodedArrayItem containing the static field initializers
+ */
+ private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
+ List staticFieldInitializers) {
+ if (staticFieldInitializers == null || staticFieldInitializers.size() == 0) {
+ return null;
+ }
+
+ int len = staticFieldInitializers.size();
+
+ 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(dexFile,
+ staticFieldInitializer.field.field.getFieldType().getTypeDescriptor())) != 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(dexFile,
+ staticFieldInitializer.field.field.getFieldType().getTypeDescriptor());
+ }
+
+ values[i] = encodedValue;
+ }
+
+ ArrayEncodedSubValue encodedArrayValue = new ArrayEncodedSubValue(values);
+ return EncodedArrayItem.getInternedEncodedArrayItem(dexFile, encodedArrayValue);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/ArrayDataPseudoInstruction.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/ArrayDataPseudoInstruction.java
index 84e45405..96847d76 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/ArrayDataPseudoInstruction.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/ArrayDataPseudoInstruction.java
@@ -1,138 +1,138 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-import org.jf.dexlib.DexFile;
-
-import java.util.Iterator;
-
-public class ArrayDataPseudoInstruction extends Instruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- @Override
- public int getSize() {
- int size = getElementWidth() * getElementCount();
- return size + (size & 0x01) + 8;
- }
-
- public static void emit(Output out, int elementWidth, byte[] encodedValues) {
- if (encodedValues.length % elementWidth != 0) {
- throw new RuntimeException("There are not a whole number of " + elementWidth + " byte elements");
- }
-
- //write out padding, if necessary
- if (out.getCursor() % 4 != 0) {
- out.writeShort(0);
- }
-
- int elementCount = encodedValues.length / elementWidth;
-
- out.writeByte(0x00);
- out.writeByte(0x03);
- out.writeShort(elementWidth);
- out.writeInt(elementCount);
- out.write(encodedValues);
- if ((encodedValues.length % 2) != 0) {
- //must write out an even number of bytes
- out.writeByte(0);
- }
- }
-
- public ArrayDataPseudoInstruction(byte[] buffer, int bufferIndex) {
- super(Opcode.NOP, buffer, bufferIndex);
-
- byte opcodeByte = buffer[bufferIndex++];
- if (opcodeByte != 0x00) {
- throw new RuntimeException("Invalid opcode byte for an ArrayData pseudo-instruction");
- }
-
- byte subopcodeByte = buffer[bufferIndex];
- if (subopcodeByte != 0x03) {
- throw new RuntimeException("Invalid sub-opcode byte for an ArrayData pseudo-instruction");
- }
- }
-
- public Format getFormat() {
- return Format.ArrayData;
- }
-
- public int getElementWidth() {
- return NumberUtils.decodeUnsignedShort(buffer[bufferIndex+2], buffer[bufferIndex+3]);
- }
-
- public int getElementCount() {
- return NumberUtils.decodeInt(buffer, bufferIndex+4);
- }
-
- 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 getElements() {
- return new Iterator() {
- final int elementCount = getElementCount();
- int i=0;
- int position = bufferIndex + 8;
- final ArrayElement arrayElement = new ArrayElement(buffer, getElementWidth());
-
- public boolean hasNext() {
- return i getElements() {
+ return new Iterator() {
+ final int elementCount = getElementCount();
+ int i=0;
+ int position = bufferIndex + 8;
+ final ArrayElement arrayElement = new ArrayElement(buffer, getElementWidth());
+
+ public boolean hasNext() {
+ return i= 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");
- }
-
- out.writeByte(opcode.value);
- out.writeByte((litB << 4) | regA);
- }
-
- private Instruction11n(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format11n;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public long getLiteral() {
- return NumberUtils.decodeHighSignedNibble(buffer[bufferIndex + 1]);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction11n(opcode, buffer, bufferIndex);
- }
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.SingleRegisterInstruction;
+import org.jf.dexlib.Code.LiteralInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction11n extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
+ public static final InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, byte regA, byte litB) {
+ 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");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte((litB << 4) | regA);
+ }
+
+ private Instruction11n(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format11n;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public long getLiteral() {
+ return NumberUtils.decodeHighSignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction11n(opcode, buffer, bufferIndex);
+ }
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction11x.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction11x.java
index 37f62874..df874dba 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction11x.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction11x.java
@@ -1,67 +1,67 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.SingleRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction11x extends Instruction implements SingleRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- }
-
- private Instruction11x(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format11x;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction11x(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.SingleRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction11x extends Instruction implements SingleRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ }
+
+ private Instruction11x(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format11x;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction11x(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction12x.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction12x.java
index 2c6443e1..299312d3 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction12x.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction12x.java
@@ -1,72 +1,72 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.TwoRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction12x extends Instruction implements TwoRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, byte regA, byte regB) {
- if (regA >= 1 << 4 ||
- regB >= 1 << 4) {
- throw new RuntimeException("The register number must be less than v16");
- }
-
- out.writeByte(opcode.value);
- out.writeByte((regB << 4) | regA);
- }
-
- private Instruction12x(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format12x;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction12x(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.TwoRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction12x extends Instruction implements TwoRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, byte regA, byte regB) {
+ if (regA >= 1 << 4 ||
+ regB >= 1 << 4) {
+ throw new RuntimeException("The register number must be less than v16");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte((regB << 4) | regA);
+ }
+
+ private Instruction12x(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format12x;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction12x(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java
index 6ea48a9d..6168bc19 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction20t.java
@@ -1,72 +1,72 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.OffsetInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction20t extends Instruction implements OffsetInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short offA) {
- if (offA == 0) {
- throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(0);
- out.writeShort(offA);
- }
-
- private Instruction20t(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
-
- if (getOffset() == 0) {
- throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
- }
- }
-
- public Format getFormat() {
- return Format.Format20t;
- }
-
- public int getOffset() {
- return NumberUtils.decodeShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction20t(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.OffsetInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction20t extends Instruction implements OffsetInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short offA) {
+ if (offA == 0) {
+ throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(0);
+ out.writeShort(offA);
+ }
+
+ private Instruction20t(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+
+ if (getOffset() == 0) {
+ throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
+ }
+ }
+
+ public Format getFormat() {
+ return Format.Format20t;
+ }
+
+ public int getOffset() {
+ return NumberUtils.decodeShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction20t(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java
index 6b56e55e..e4bbcc30 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java
@@ -1,82 +1,82 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.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.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction21c extends InstructionWithReference implements SingleRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, Item 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");
- }
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeShort(0);
- }
-
- 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");
- }
- }
-
- public Format getFormat() {
- return Format.Format21c;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- 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);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.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.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction21c extends InstructionWithReference implements SingleRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, Item 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");
+ }
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeShort(0);
+ }
+
+ 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");
+ }
+ }
+
+ public Format getFormat() {
+ return Format.Format21c;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ 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);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21h.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21h.java
index 0fd20c90..1f87d878 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21h.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21h.java
@@ -1,73 +1,73 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.LiteralInstruction;
-import org.jf.dexlib.Code.SingleRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction21h extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, short litB) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeShort(litB);
- }
-
- private Instruction21h(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format21h;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public long getLiteral() {
- return NumberUtils.decodeShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction21h(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.LiteralInstruction;
+import org.jf.dexlib.Code.SingleRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction21h extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, short litB) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeShort(litB);
+ }
+
+ private Instruction21h(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format21h;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public long getLiteral() {
+ return NumberUtils.decodeShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction21h(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21s.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21s.java
index 88462552..e37aefd9 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21s.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21s.java
@@ -1,73 +1,73 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.LiteralInstruction;
-import org.jf.dexlib.Code.SingleRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction21s extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, short litB) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeShort(litB);
- }
-
- private Instruction21s(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format21s;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public long getLiteral() {
- return NumberUtils.decodeShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction21s(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.LiteralInstruction;
+import org.jf.dexlib.Code.SingleRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction21s extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, short litB) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeShort(litB);
+ }
+
+ private Instruction21s(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format21s;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public long getLiteral() {
+ return NumberUtils.decodeShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction21s(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java
index 02980b4d..83288859 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21t.java
@@ -1,80 +1,80 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.OffsetInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction21t extends Instruction implements OffsetInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, short offB) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- if (offB == 0) {
- throw new RuntimeException("The offset cannot be 0.");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeShort(offB);
- }
-
- private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
-
- if (getOffset() == 0) {
- throw new RuntimeException("The offset cannot be 0.");
- }
- }
-
- public Format getFormat() {
- return Format.Format21t;
- }
-
- public short getRegister() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public int getOffset() {
- return NumberUtils.decodeShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction21t(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.OffsetInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction21t extends Instruction implements OffsetInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, short offB) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ if (offB == 0) {
+ throw new RuntimeException("The offset cannot be 0.");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeShort(offB);
+ }
+
+ private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+
+ if (getOffset() == 0) {
+ throw new RuntimeException("The offset cannot be 0.");
+ }
+ }
+
+ public Format getFormat() {
+ return Format.Format21t;
+ }
+
+ public short getRegister() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public int getOffset() {
+ return NumberUtils.decodeShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction21t(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22b.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22b.java
index 7a7b6380..a7d19b07 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22b.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22b.java
@@ -1,78 +1,78 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.TwoRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction22b extends Instruction implements TwoRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, short regB, byte litC) {
- if (regA >= 1 << 8 ||
- regB >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeByte(regB);
- out.writeByte(litC);
- }
-
- private Instruction22b(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format22b;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 2]);
- }
-
- public byte getLiteral() {
- return buffer[bufferIndex + 3];
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction22b(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.TwoRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction22b extends Instruction implements TwoRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, short regB, byte litC) {
+ if (regA >= 1 << 8 ||
+ regB >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeByte(regB);
+ out.writeByte(litC);
+ }
+
+ private Instruction22b(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format22b;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 2]);
+ }
+
+ public byte getLiteral() {
+ return buffer[bufferIndex + 3];
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction22b(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java
index 8040869b..37019c56 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java
@@ -1,74 +1,74 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.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.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction22c extends InstructionWithReference implements TwoRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, byte regA, byte regB) {
- if (regA >= 1 << 4 ||
- regB >= 1 << 4) {
- throw new RuntimeException("The register number must be less than v16");
- }
-
- out.writeByte(opcode.value);
- out.writeByte((regB << 4) | regA);
- out.writeShort(0);
- }
-
- private Instruction22c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- super(dexFile, opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format22c;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- 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);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.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.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction22c extends InstructionWithReference implements TwoRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, byte regA, byte regB) {
+ if (regA >= 1 << 4 ||
+ regB >= 1 << 4) {
+ throw new RuntimeException("The register number must be less than v16");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte((regB << 4) | regA);
+ out.writeShort(0);
+ }
+
+ private Instruction22c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(dexFile, opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format22c;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction22c(dexFile, opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22s.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22s.java
index 2e2e09f0..8c7c8176 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22s.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22s.java
@@ -1,77 +1,77 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.TwoRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction22s extends Instruction implements TwoRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, byte regA, byte regB, short litC) {
- if (regA >= 1 << 4 ||
- regB >= 1 << 4) {
- throw new RuntimeException("The register number must be less than v16");
- }
-
- out.writeByte(opcode.value);
- out.writeByte((regB << 4) | regA);
- out.writeShort(litC);
- }
-
- private Instruction22s(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format22s;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public short getLiteral() {
- return NumberUtils.decodeShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction22s(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.TwoRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction22s extends Instruction implements TwoRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, byte regA, byte regB, short litC) {
+ if (regA >= 1 << 4 ||
+ regB >= 1 << 4) {
+ throw new RuntimeException("The register number must be less than v16");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte((regB << 4) | regA);
+ out.writeShort(litC);
+ }
+
+ private Instruction22s(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format22s;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public short getLiteral() {
+ return NumberUtils.decodeShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction22s(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java
index caacb1da..241039f0 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22t.java
@@ -1,85 +1,85 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.OffsetInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction22t extends Instruction implements OffsetInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, byte regA, byte regB, short offC) {
- if (regA >= 1 << 4 ||
- regB >= 1 << 4) {
- throw new RuntimeException("The register number must be less than v16");
- }
-
- if (offC == 0) {
- throw new RuntimeException("The offset cannot be 0.");
- }
-
- out.writeByte(opcode.value);
- out.writeByte((regB << 4) | regA);
- out.writeShort(offC);
- }
-
- private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
-
- if (getOffset() == 0) {
- throw new RuntimeException("The offset cannot be 0.");
- }
- }
-
- public Format getFormat() {
- return Format.Format22t;
- }
-
- public byte getRegisterA() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public byte getRegisterB() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public int getOffset() {
- return NumberUtils.decodeShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction22t(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.OffsetInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction22t extends Instruction implements OffsetInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, byte regA, byte regB, short offC) {
+ if (regA >= 1 << 4 ||
+ regB >= 1 << 4) {
+ throw new RuntimeException("The register number must be less than v16");
+ }
+
+ if (offC == 0) {
+ throw new RuntimeException("The offset cannot be 0.");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte((regB << 4) | regA);
+ out.writeShort(offC);
+ }
+
+ private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+
+ if (getOffset() == 0) {
+ throw new RuntimeException("The offset cannot be 0.");
+ }
+ }
+
+ public Format getFormat() {
+ return Format.Format22t;
+ }
+
+ public byte getRegisterA() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public byte getRegisterB() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public int getOffset() {
+ return NumberUtils.decodeShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction22t(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22x.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22x.java
index c9081f0f..77bd4b20 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22x.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22x.java
@@ -1,76 +1,76 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.TwoRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction22x extends Instruction implements TwoRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, int regB) {
- 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");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeShort(regB);
- }
-
- private Instruction22x(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format22x;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction22x(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.TwoRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction22x extends Instruction implements TwoRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, int regB) {
+ 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");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeShort(regB);
+ }
+
+ private Instruction22x(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format22x;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction22x(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction23x.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction23x.java
index 4a27cf59..addb9fad 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction23x.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction23x.java
@@ -1,79 +1,79 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.ThreeRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction23x extends Instruction implements ThreeRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, short regB, short regC) {
- if (regA >= 1 << 8 ||
- regB >= 1 << 8 ||
- regC >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeByte(regB);
- out.writeByte(regC);
- }
-
- private Instruction23x(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format23x;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 2]);
- }
-
- public int getRegisterC() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 3]);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction23x(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.ThreeRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction23x extends Instruction implements ThreeRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, short regB, short regC) {
+ if (regA >= 1 << 8 ||
+ regB >= 1 << 8 ||
+ regC >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeByte(regB);
+ out.writeByte(regC);
+ }
+
+ private Instruction23x(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format23x;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 2]);
+ }
+
+ public int getRegisterC() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 3]);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction23x(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java
index 5c3f1b0d..d7ba1f27 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction30t.java
@@ -1,64 +1,64 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.DexFile;
-import org.jf.dexlib.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.OffsetInstruction;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction30t extends Instruction implements OffsetInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, int offA) {
- out.writeByte(opcode.value);
- out.writeByte(0);
- out.writeInt(offA);
- }
-
- private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format30t;
- }
-
- public int getOffset() {
- return NumberUtils.decodeInt(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction30t(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.DexFile;
+import org.jf.dexlib.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.OffsetInstruction;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction30t extends Instruction implements OffsetInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, int offA) {
+ out.writeByte(opcode.value);
+ out.writeByte(0);
+ out.writeInt(offA);
+ }
+
+ private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format30t;
+ }
+
+ public int getOffset() {
+ return NumberUtils.decodeInt(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction30t(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31c.java
index 5eccff74..0f3a05d5 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31c.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31c.java
@@ -1,74 +1,74 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.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.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction31c extends InstructionWithReference implements SingleRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeInt(0);
- }
-
- private Instruction31c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- super(dexFile, opcode, buffer, bufferIndex);
- }
-
- protected int getReferencedItemIndex() {
- return NumberUtils.decodeInt(buffer, bufferIndex + 2);
- }
-
- public Format getFormat() {
- return Format.Format31c;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- 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);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.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.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction31c extends InstructionWithReference implements SingleRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeInt(0);
+ }
+
+ private Instruction31c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(dexFile, opcode, buffer, bufferIndex);
+ }
+
+ protected int getReferencedItemIndex() {
+ return NumberUtils.decodeInt(buffer, bufferIndex + 2);
+ }
+
+ public Format getFormat() {
+ return Format.Format31c;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ 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);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31i.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31i.java
index 43d0ae2b..c15695e5 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31i.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31i.java
@@ -1,73 +1,73 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.LiteralInstruction;
-import org.jf.dexlib.Code.SingleRegisterInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction31i extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, int litB) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeInt(litB);
- }
-
- private Instruction31i(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format31i;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public long getLiteral() {
- return NumberUtils.decodeInt(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction31i(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.LiteralInstruction;
+import org.jf.dexlib.Code.SingleRegisterInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction31i extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, int litB) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeInt(litB);
+ }
+
+ private Instruction31i(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format31i;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public long getLiteral() {
+ return NumberUtils.decodeInt(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction31i(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java
index 0cf455cf..f4c297a3 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction31t.java
@@ -1,72 +1,72 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.OffsetInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction31t extends Instruction implements OffsetInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, int offB) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeInt(offB);
- }
-
- private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format31t;
- }
-
- public short getRegister() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public int getOffset() {
- return NumberUtils.decodeInt(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction31t(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.OffsetInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction31t extends Instruction implements OffsetInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, int offB) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeInt(offB);
+ }
+
+ private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format31t;
+ }
+
+ public short getRegister() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public int getOffset() {
+ return NumberUtils.decodeInt(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction31t(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction32x.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction32x.java
index ad3097c0..e09ea642 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction32x.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction32x.java
@@ -1,74 +1,74 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.DexFile;
-import org.jf.dexlib.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.TwoRegisterInstruction;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction32x extends Instruction implements TwoRegisterInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, int regA, int regB) {
- if (regA >= 1<<16 ||
- regB >= 1<<16) {
- throw new RuntimeException("The register number must be less than v65536");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(0);
- out.writeShort(regA);
- out.writeShort(regB);
- }
-
- private Instruction32x(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format32x;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
- }
-
- public int getRegisterB() {
- return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction32x(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.DexFile;
+import org.jf.dexlib.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.TwoRegisterInstruction;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction32x extends Instruction implements TwoRegisterInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, int regA, int regB) {
+ if (regA >= 1<<16 ||
+ regB >= 1<<16) {
+ throw new RuntimeException("The register number must be less than v65536");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(0);
+ out.writeShort(regA);
+ out.writeShort(regB);
+ }
+
+ private Instruction32x(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format32x;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
+ }
+
+ public int getRegisterB() {
+ return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction32x(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java
index dddf6741..b8dddbf6 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction35c.java
@@ -1,134 +1,134 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.InstructionWithReference;
-import org.jf.dexlib.Code.Opcode;
-import static 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.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction35c extends InstructionWithReference {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
- byte regA, Item 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");
- }
-
- out.writeByte(opcode.value);
- out.writeByte((regCount << 4) | regA);
- out.writeShort(0);
- out.writeByte((regE << 4) | regD);
- out.writeByte((regG << 4) | regF);
-
- checkItem(opcode, referencedItem, regCount);
- }
-
- protected Instruction35c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- super(dexFile, opcode, buffer, bufferIndex);
-
- if (getRegCount() > 5) {
- throw new RuntimeException("regCount cannot be greater than 5");
- }
-
- checkItem(opcode, getReferencedItem(), getRegCount());
- }
-
- public Format getFormat() {
- return Format.Format35c;
- }
-
- public byte getRegisterA() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public byte getRegCount() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
- }
-
- public byte getRegisterD() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]);
- }
-
- public byte getRegisterE() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 4]);
- }
-
- public byte getRegisterF() {
- return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]);
- }
-
- public byte getRegisterG() {
- return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
- }
-
- 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) {
- //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);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.InstructionWithReference;
+import org.jf.dexlib.Code.Opcode;
+import static 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.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction35c extends InstructionWithReference {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
+ byte regA, Item 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");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte((regCount << 4) | regA);
+ out.writeShort(0);
+ out.writeByte((regE << 4) | regD);
+ out.writeByte((regG << 4) | regF);
+
+ checkItem(opcode, referencedItem, regCount);
+ }
+
+ protected Instruction35c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(dexFile, opcode, buffer, bufferIndex);
+
+ if (getRegCount() > 5) {
+ throw new RuntimeException("regCount cannot be greater than 5");
+ }
+
+ checkItem(opcode, getReferencedItem(), getRegCount());
+ }
+
+ public Format getFormat() {
+ return Format.Format35c;
+ }
+
+ public byte getRegisterA() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public byte getRegCount() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 1]);
+ }
+
+ public byte getRegisterD() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 4]);
+ }
+
+ public byte getRegisterE() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 4]);
+ }
+
+ public byte getRegisterF() {
+ return NumberUtils.decodeLowUnsignedNibble(buffer[bufferIndex + 5]);
+ }
+
+ public byte getRegisterG() {
+ return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
+ }
+
+ 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) {
+ //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);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java
index af26c1f5..5975bc49 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java
@@ -1,114 +1,114 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.InstructionWithReference;
-import org.jf.dexlib.Code.Opcode;
-import static 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.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction3rc extends InstructionWithReference {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regCount, int startReg, Item 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");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regCount);
- out.writeShort(0);
- out.writeShort(startReg);
-
- checkItem(opcode, referencedItem, regCount);
- }
-
- private Instruction3rc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- super(dexFile, opcode, buffer, bufferIndex);
-
- checkItem(opcode, getReferencedItem(), getRegCount());
- }
-
- public Format getFormat() {
- return Format.Format3rc;
- }
-
- public short getRegCount() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public int getStartRegister() {
- return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
- }
-
- 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) {
- //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);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.InstructionWithReference;
+import org.jf.dexlib.Code.Opcode;
+import static 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.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction3rc extends InstructionWithReference {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regCount, int startReg, Item 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");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regCount);
+ out.writeShort(0);
+ out.writeShort(startReg);
+
+ checkItem(opcode, referencedItem, regCount);
+ }
+
+ private Instruction3rc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(dexFile, opcode, buffer, bufferIndex);
+
+ checkItem(opcode, getReferencedItem(), getRegCount());
+ }
+
+ public Format getFormat() {
+ return Format.Format3rc;
+ }
+
+ public short getRegCount() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public int getStartRegister() {
+ return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
+ }
+
+ 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) {
+ //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);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction51l.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction51l.java
index f0fe0334..a3f06ed5 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction51l.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction51l.java
@@ -1,73 +1,73 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Code.SingleRegisterInstruction;
-import org.jf.dexlib.Code.LiteralInstruction;
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-
-public class Instruction51l extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- public static void emit(Output out, Opcode opcode, short regA, long litB) {
- if (regA >= 1 << 8) {
- throw new RuntimeException("The register number must be less than v256");
- }
-
- out.writeByte(opcode.value);
- out.writeByte(regA);
- out.writeLong(litB);
- }
-
- private Instruction51l(Opcode opcode, byte[] buffer, int bufferIndex) {
- super(opcode, buffer, bufferIndex);
- }
-
- public Format getFormat() {
- return Format.Format51l;
- }
-
- public int getRegisterA() {
- return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
- }
-
- public long getLiteral() {
- return NumberUtils.decodeLong(buffer, bufferIndex + 2);
- }
-
- private static class Factory implements Instruction.InstructionFactory {
- public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
- return new Instruction51l(opcode, buffer, bufferIndex);
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Code.Instruction;
+import org.jf.dexlib.Code.Opcode;
+import org.jf.dexlib.Code.SingleRegisterInstruction;
+import org.jf.dexlib.Code.LiteralInstruction;
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.Util.NumberUtils;
+import org.jf.dexlib.Util.Output;
+
+public class Instruction51l extends Instruction implements SingleRegisterInstruction, LiteralInstruction {
+ public static final Instruction.InstructionFactory Factory = new Factory();
+
+ public static void emit(Output out, Opcode opcode, short regA, long litB) {
+ if (regA >= 1 << 8) {
+ throw new RuntimeException("The register number must be less than v256");
+ }
+
+ out.writeByte(opcode.value);
+ out.writeByte(regA);
+ out.writeLong(litB);
+ }
+
+ private Instruction51l(Opcode opcode, byte[] buffer, int bufferIndex) {
+ super(opcode, buffer, bufferIndex);
+ }
+
+ public Format getFormat() {
+ return Format.Format51l;
+ }
+
+ public int getRegisterA() {
+ return NumberUtils.decodeUnsignedByte(buffer[bufferIndex + 1]);
+ }
+
+ public long getLiteral() {
+ return NumberUtils.decodeLong(buffer, bufferIndex + 2);
+ }
+
+ private static class Factory implements Instruction.InstructionFactory {
+ public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
+ return new Instruction51l(opcode, buffer, bufferIndex);
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/PackedSwitchDataPseudoInstruction.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/PackedSwitchDataPseudoInstruction.java
index 48283050..eabccf87 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/PackedSwitchDataPseudoInstruction.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/PackedSwitchDataPseudoInstruction.java
@@ -1,136 +1,136 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Code.Instruction;
-import org.jf.dexlib.Code.Opcode;
-import org.jf.dexlib.Util.NumberUtils;
-import org.jf.dexlib.Util.Output;
-import org.jf.dexlib.DexFile;
-
-import java.util.Iterator;
-
-public class PackedSwitchDataPseudoInstruction extends Instruction {
- public static final Instruction.InstructionFactory Factory = new Factory();
-
- @Override
- public int getSize() {
- return getTargetCount() * 4 + 8;
- }
-
- public static void emit(Output out, int firstKey, int[] targets) {
- if (targets.length > 0xFFFF) {
- throw new RuntimeException("The packed-switch data contains too many elements. " +
- "The maximum number of switch elements is 65535");
- }
-
- //write out padding, if necessary
- if (out.getCursor() % 4 != 0) {
- out.writeShort(0);
- }
-
- out.writeByte(0x00);
- out.writeByte(0x01);
- out.writeShort(targets.length);
- out.writeInt(firstKey);
-
- for (int target : targets) {
- out.writeInt(target);
- }
- }
-
- public PackedSwitchDataPseudoInstruction(byte[] buffer, int bufferIndex) {
- super(Opcode.NOP, buffer, bufferIndex);
-
- byte opcodeByte = buffer[bufferIndex++];
- if (opcodeByte != 0x00) {
- throw new RuntimeException("Invalid opcode byte for a PackedSwitchData pseudo-instruction");
- }
- byte subopcodeByte = buffer[bufferIndex];
- if (subopcodeByte != 0x01) {
- throw new RuntimeException("Invalid sub-opcode byte for a PackedSwitchData pseudo-instruction");
- }
- }
-
- public Format getFormat() {
- return Format.PackedSwitchData;
- }
-
- public int getTargetCount() {
- return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
- }
-
- public int getFirstKey() {
- return NumberUtils.decodeInt(buffer, bufferIndex + 4);
- }
-
- public static class PackedSwitchTarget {
- public int value;
- public int target;
- }
-
- public Iterator getTargets() {
- return new Iterator() {
- final int targetCount = getTargetCount();
- int i = 0;
- int position = bufferIndex + 8;
- int value = getFirstKey();
-
- PackedSwitchTarget packedSwitchTarget = new PackedSwitchTarget();
-
- public boolean hasNext() {
- return i 0xFFFF) {
+ throw new RuntimeException("The packed-switch data contains too many elements. " +
+ "The maximum number of switch elements is 65535");
+ }
+
+ //write out padding, if necessary
+ if (out.getCursor() % 4 != 0) {
+ out.writeShort(0);
+ }
+
+ out.writeByte(0x00);
+ out.writeByte(0x01);
+ out.writeShort(targets.length);
+ out.writeInt(firstKey);
+
+ for (int target : targets) {
+ out.writeInt(target);
+ }
+ }
+
+ public PackedSwitchDataPseudoInstruction(byte[] buffer, int bufferIndex) {
+ super(Opcode.NOP, buffer, bufferIndex);
+
+ byte opcodeByte = buffer[bufferIndex++];
+ if (opcodeByte != 0x00) {
+ throw new RuntimeException("Invalid opcode byte for a PackedSwitchData pseudo-instruction");
+ }
+ byte subopcodeByte = buffer[bufferIndex];
+ if (subopcodeByte != 0x01) {
+ throw new RuntimeException("Invalid sub-opcode byte for a PackedSwitchData pseudo-instruction");
+ }
+ }
+
+ public Format getFormat() {
+ return Format.PackedSwitchData;
+ }
+
+ public int getTargetCount() {
+ return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
+ }
+
+ public int getFirstKey() {
+ return NumberUtils.decodeInt(buffer, bufferIndex + 4);
+ }
+
+ public static class PackedSwitchTarget {
+ public int value;
+ public int target;
+ }
+
+ public Iterator getTargets() {
+ return new Iterator() {
+ final int targetCount = getTargetCount();
+ int i = 0;
+ int position = bufferIndex + 8;
+ int value = getFirstKey();
+
+ PackedSwitchTarget packedSwitchTarget = new PackedSwitchTarget();
+
+ public boolean hasNext() {
+ return i 0xFFFF) {
- throw new RuntimeException("The sparse-switch data contains too many elements. " +
- "The maximum number of switch elements is 65535");
- }
-
- //write out padding, if necessary
- if (out.getCursor() % 4 != 0) {
- out.writeShort(0);
- }
-
- 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];
- if (key <= keys[i - 1]) {
- throw new RuntimeException("The targets in a sparse switch block must be sorted in ascending" +
- "order, by key");
- }
- out.writeInt(key);
- }
-
- for (int target : targets) {
- out.writeInt(target);
- }
- }
- }
-
- public SparseSwitchDataPseudoInstruction(byte[] buffer, int bufferIndex) {
- super(Opcode.NOP, buffer, bufferIndex);
-
- byte opcodeByte = buffer[bufferIndex++];
- if (opcodeByte != 0x00) {
- throw new RuntimeException("Invalid opcode byte for a SparseSwitchData pseudo-instruction");
- }
- byte subopcodeByte = buffer[bufferIndex];
- if (subopcodeByte != 0x02) {
- throw new RuntimeException("Invalid sub-opcode byte for a SparseSwitchData pseudo-instruction");
- }
- }
-
- public Format getFormat() {
- return Format.SparseSwitchData;
- }
-
- public int getTargetCount() {
- return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
- }
-
- public static class SparseSwitchTarget {
- public int value;
- public int target;
- }
-
- public Iterator getTargets() {
- return new Iterator() {
- final int targetCount = getTargetCount();
- int i = 0;
- int valuePosition = bufferIndex + 4;
- int targetPosition = bufferIndex + 4 + targetCount * 4;
-
- SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
-
- public boolean hasNext() {
- return i 0xFFFF) {
+ throw new RuntimeException("The sparse-switch data contains too many elements. " +
+ "The maximum number of switch elements is 65535");
+ }
+
+ //write out padding, if necessary
+ if (out.getCursor() % 4 != 0) {
+ out.writeShort(0);
+ }
+
+ 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];
+ if (key <= keys[i - 1]) {
+ throw new RuntimeException("The targets in a sparse switch block must be sorted in ascending" +
+ "order, by key");
+ }
+ out.writeInt(key);
+ }
+
+ for (int target : targets) {
+ out.writeInt(target);
+ }
+ }
+ }
+
+ public SparseSwitchDataPseudoInstruction(byte[] buffer, int bufferIndex) {
+ super(Opcode.NOP, buffer, bufferIndex);
+
+ byte opcodeByte = buffer[bufferIndex++];
+ if (opcodeByte != 0x00) {
+ throw new RuntimeException("Invalid opcode byte for a SparseSwitchData pseudo-instruction");
+ }
+ byte subopcodeByte = buffer[bufferIndex];
+ if (subopcodeByte != 0x02) {
+ throw new RuntimeException("Invalid sub-opcode byte for a SparseSwitchData pseudo-instruction");
+ }
+ }
+
+ public Format getFormat() {
+ return Format.SparseSwitchData;
+ }
+
+ public int getTargetCount() {
+ return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 2);
+ }
+
+ public static class SparseSwitchTarget {
+ public int value;
+ public int target;
+ }
+
+ public Iterator getTargets() {
+ return new Iterator() {
+ final int targetCount = getTargetCount();
+ int i = 0;
+ int valuePosition = bufferIndex + 4;
+ int targetPosition = bufferIndex + 4 + targetCount * 4;
+
+ SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
+
+ public boolean hasNext() {
+ return i opcodesByName;
-
- static {
- opcodesByValue = new Opcode[256];
- opcodesByName = new HashMap();
-
- for (Opcode opcode: Opcode.values()) {
- opcodesByValue[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(byte opcodeValue) {
- return opcodesByValue[opcodeValue & 0xFF];
- }
-
- public final byte value;
- public final String name;
- public final ReferenceType referenceType;
- public final Format format;
- public final boolean odexOnly;
-
- Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format) {
- this(opcodeValue, opcodeName, referenceType, format, false);
- }
-
- Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format, boolean odexOnly) {
- this.value = opcodeValue;
- this.name = opcodeName;
- this.referenceType = referenceType;
- this.format = format;
- this.odexOnly = odexOnly;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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 org.jf.dexlib.Code.Format.Format;
+
+import java.util.HashMap;
+
+public enum Opcode
+{
+ NOP((byte)0x00, "nop", ReferenceType.none, Format.Format10x),
+ MOVE((byte)0x01, "move", ReferenceType.none, Format.Format12x),
+ MOVE_FROM16((byte)0x02, "move/from16", ReferenceType.none, Format.Format22x),
+ MOVE_16((byte)0x03, "move/16", ReferenceType.none, Format.Format32x),
+ MOVE_WIDE((byte)0x04, "move-wide", ReferenceType.none, Format.Format12x),
+ MOVE_WIDE_FROM16((byte)0x05, "move-wide/from16", ReferenceType.none, Format.Format22x),
+ MOVE_WIDE_16((byte)0x06, "move-wide/16", ReferenceType.none, Format.Format32x),
+ MOVE_OBJECT((byte)0x07, "move-object", ReferenceType.none, Format.Format12x),
+ MOVE_OBJECT_FROM16((byte)0x08, "move-object/from16", ReferenceType.none, Format.Format22x),
+ MOVE_OBJECT_16((byte)0x09, "move-object/16", ReferenceType.none, Format.Format32x),
+ MOVE_RESULT((byte)0x0a, "move-result", ReferenceType.none, Format.Format11x),
+ MOVE_RESULT_WIDE((byte)0x0b, "move-result-wide", ReferenceType.none, Format.Format11x),
+ MOVE_RESULT_OBJECT((byte)0x0c, "move-result-object", ReferenceType.none, Format.Format11x),
+ MOVE_EXCEPTION((byte)0x0d, "move-exception", ReferenceType.none, Format.Format11x),
+ RETURN_VOID((byte)0x0e, "return-void", ReferenceType.none, Format.Format10x),
+ RETURN((byte)0x0f, "return", ReferenceType.none, Format.Format11x),
+ RETURN_WIDE((byte)0x10, "return-wide", ReferenceType.none, Format.Format11x),
+ RETURN_OBJECT((byte)0x11, "return-object", ReferenceType.none, Format.Format11x),
+ CONST_4((byte)0x12, "const/4", ReferenceType.none, Format.Format11n),
+ CONST_16((byte)0x13, "const/16", ReferenceType.none, Format.Format21s),
+ CONST((byte)0x14, "const", ReferenceType.none, Format.Format31i),
+ CONST_HIGH16((byte)0x15, "const/high16", ReferenceType.none, Format.Format21h),
+ CONST_WIDE_16((byte)0x16, "const-wide/16", ReferenceType.none, Format.Format21s),
+ CONST_WIDE_32((byte)0x17, "const-wide/32", ReferenceType.none, Format.Format31i),
+ CONST_WIDE((byte)0x18, "const-wide", ReferenceType.none, Format.Format51l),
+ CONST_WIDE_HIGH16((byte)0x19, "const-wide/high16", ReferenceType.none, Format.Format21h),
+ CONST_STRING((byte)0x1a, "const-string", ReferenceType.string, Format.Format21c),
+ CONST_STRING_JUMBO((byte)0x1b, "const-string/jumbo", ReferenceType.string, Format.Format31c),
+ CONST_CLASS((byte)0x1c, "const-class", ReferenceType.type, Format.Format21c),
+ MONITOR_ENTER((byte)0x1d, "monitor-enter", ReferenceType.none, Format.Format11x),
+ MONITOR_EXIT((byte)0x1e, "monitor-exit", ReferenceType.none, Format.Format11x),
+ CHECK_CAST((byte)0x1f, "check-cast", ReferenceType.type, Format.Format21c),
+ INSTANCE_OF((byte)0x20, "instance-of", ReferenceType.type, Format.Format22c),
+ ARRAY_LENGTH((byte)0x21, "array-length", ReferenceType.none, Format.Format12x),
+ NEW_INSTANCE((byte)0x22, "new-instance", ReferenceType.type, Format.Format21c),
+ NEW_ARRAY((byte)0x23, "new-array", ReferenceType.type, Format.Format22c),
+ FILLED_NEW_ARRAY((byte)0x24, "filled-new-array", ReferenceType.type, Format.Format35c),
+ FILLED_NEW_ARRAY_RANGE((byte)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc),
+ FILL_ARRAY_DATA((byte)0x26, "fill-array-data", ReferenceType.none, Format.Format31t),
+ THROW((byte)0x27, "throw", ReferenceType.none, Format.Format11x),
+ GOTO((byte)0x28, "goto", ReferenceType.none, Format.Format10t),
+ GOTO_16((byte)0x29, "goto/16", ReferenceType.none, Format.Format20t),
+ GOTO_32((byte)0x2a, "goto/32", ReferenceType.none, Format.Format30t),
+ PACKED_SWITCH((byte)0x2b, "packed-switch", ReferenceType.none, Format.Format31t),
+ SPARSE_SWITCH((byte)0x2c, "sparse-switch", ReferenceType.none, Format.Format31t),
+ CMPL_FLOAT((byte)0x2d, "cmpl-float", ReferenceType.none, Format.Format23x),
+ CMPG_FLOAT((byte)0x2e, "cmpg-float", ReferenceType.none, Format.Format23x),
+ CMPL_DOUBLE((byte)0x2f, "cmpl-double", ReferenceType.none, Format.Format23x),
+ CMPG_DOUBLE((byte)0x30, "cmpg-double", ReferenceType.none, Format.Format23x),
+ CMP_LONG((byte)0x31, "cmp-long", ReferenceType.none, Format.Format23x),
+ IF_EQ((byte)0x32, "if-eq", ReferenceType.none, Format.Format22t),
+ IF_NE((byte)0x33, "if-ne", ReferenceType.none, Format.Format22t),
+ IF_LT((byte)0x34, "if-lt", ReferenceType.none, Format.Format22t),
+ IF_GE((byte)0x35, "if-ge", ReferenceType.none, Format.Format22t),
+ IF_GT((byte)0x36, "if-gt", ReferenceType.none, Format.Format22t),
+ IF_LE((byte)0x37, "if-le", ReferenceType.none, Format.Format22t),
+ IF_EQZ((byte)0x38, "if-eqz", ReferenceType.none, Format.Format21t),
+ IF_NEZ((byte)0x39, "if-nez", ReferenceType.none, Format.Format21t),
+ IF_LTZ((byte)0x3a, "if-ltz", ReferenceType.none, Format.Format21t),
+ IF_GEZ((byte)0x3b, "if-gez", ReferenceType.none, Format.Format21t),
+ IF_GTZ((byte)0x3c, "if-gtz", ReferenceType.none, Format.Format21t),
+ IF_LEZ((byte)0x3d, "if-lez", ReferenceType.none, Format.Format21t),
+ AGET((byte)0x44, "aget", ReferenceType.none, Format.Format23x),
+ AGET_WIDE((byte)0x45, "aget-wide", ReferenceType.none, Format.Format23x),
+ AGET_OBJECT((byte)0x46, "aget-object", ReferenceType.none, Format.Format23x),
+ AGET_BOOLEAN((byte)0x47, "aget-boolean", ReferenceType.none, Format.Format23x),
+ AGET_BYTE((byte)0x48, "aget-byte", ReferenceType.none, Format.Format23x),
+ AGET_CHAR((byte)0x49, "aget-char", ReferenceType.none, Format.Format23x),
+ AGET_SHORT((byte)0x4a, "aget-short", ReferenceType.none, Format.Format23x),
+ APUT((byte)0x4b, "aput", ReferenceType.none, Format.Format23x),
+ APUT_WIDE((byte)0x4c, "aput-wide", ReferenceType.none, Format.Format23x),
+ APUT_OBJECT((byte)0x4d, "aput-object", ReferenceType.none, Format.Format23x),
+ APUT_BOOLEAN((byte)0x4e, "aput-boolean", ReferenceType.none, Format.Format23x),
+ APUT_BYTE((byte)0x4f, "aput-byte", ReferenceType.none, Format.Format23x),
+ APUT_CHAR((byte)0x50, "aput-char", ReferenceType.none, Format.Format23x),
+ APUT_SHORT((byte)0x51, "aput-short", ReferenceType.none, Format.Format23x),
+ IGET((byte)0x52, "iget", ReferenceType.field, Format.Format22c),
+ IGET_WIDE((byte)0x53, "iget-wide", ReferenceType.field, Format.Format22c),
+ IGET_OBJECT((byte)0x54, "iget-object", ReferenceType.field, Format.Format22c),
+ IGET_BOOLEAN((byte)0x55, "iget-boolean", ReferenceType.field, Format.Format22c),
+ IGET_BYTE((byte)0x56, "iget-byte", ReferenceType.field, Format.Format22c),
+ IGET_CHAR((byte)0x57, "iget-char", ReferenceType.field, Format.Format22c),
+ IGET_SHORT((byte)0x58, "iget-short", ReferenceType.field, Format.Format22c),
+ IPUT((byte)0x59, "iput", ReferenceType.field, Format.Format22c),
+ IPUT_WIDE((byte)0x5a, "iput-wide", ReferenceType.field, Format.Format22c),
+ IPUT_OBJECT((byte)0x5b, "iput-object", ReferenceType.field, Format.Format22c),
+ IPUT_BOOLEAN((byte)0x5c, "iput-boolean", ReferenceType.field, Format.Format22c),
+ IPUT_BYTE((byte)0x5d, "iput-byte", ReferenceType.field, Format.Format22c),
+ IPUT_CHAR((byte)0x5e, "iput-char", ReferenceType.field, Format.Format22c),
+ IPUT_SHORT((byte)0x5f, "iput-short", ReferenceType.field, Format.Format22c),
+ SGET((byte)0x60, "sget", ReferenceType.field, Format.Format21c),
+ SGET_WIDE((byte)0x61, "sget-wide", ReferenceType.field, Format.Format21c),
+ SGET_OBJECT((byte)0x62, "sget-object", ReferenceType.field, Format.Format21c),
+ SGET_BOOLEAN((byte)0x63, "sget-boolean", ReferenceType.field, Format.Format21c),
+ SGET_BYTE((byte)0x64, "sget-byte", ReferenceType.field, Format.Format21c),
+ SGET_CHAR((byte)0x65, "sget-char", ReferenceType.field, Format.Format21c),
+ SGET_SHORT((byte)0x66, "sget-short", ReferenceType.field, Format.Format21c),
+ SPUT((byte)0x67, "sput", ReferenceType.field, Format.Format21c),
+ SPUT_WIDE((byte)0x68, "sput-wide", ReferenceType.field, Format.Format21c),
+ SPUT_OBJECT((byte)0x69, "sput-object", ReferenceType.field, Format.Format21c),
+ SPUT_BOOLEAN((byte)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c),
+ SPUT_BYTE((byte)0x6b, "sput-byte", ReferenceType.field, Format.Format21c),
+ SPUT_CHAR((byte)0x6c, "sput-char", ReferenceType.field, Format.Format21c),
+ SPUT_SHORT((byte)0x6d, "sput-short", ReferenceType.field, Format.Format21c),
+ INVOKE_VIRTUAL((byte)0x6e, "invoke-virtual", ReferenceType.method, Format.Format35c),
+ INVOKE_SUPER((byte)0x6f, "invoke-super", ReferenceType.method, Format.Format35c),
+ INVOKE_DIRECT((byte)0x70, "invoke-direct", ReferenceType.method, Format.Format35c),
+ INVOKE_STATIC((byte)0x71, "invoke-static", ReferenceType.method, Format.Format35c),
+ INVOKE_INTERFACE((byte)0x72, "invoke-interface", ReferenceType.method, Format.Format35c),
+ INVOKE_VIRTUAL_RANGE((byte)0x74, "invoke-virtual/range", ReferenceType.method, Format.Format3rc),
+ INVOKE_SUPER_RANGE((byte)0x75, "invoke-super/range", ReferenceType.method, Format.Format3rc),
+ INVOKE_DIRECT_RANGE((byte)0x76, "invoke-direct/range", ReferenceType.method, Format.Format3rc),
+ INVOKE_STATIC_RANGE((byte)0x77, "invoke-static/range", ReferenceType.method, Format.Format3rc),
+ INVOKE_INTERFACE_RANGE((byte)0x78, "invoke-interface/range", ReferenceType.method, Format.Format3rc),
+ NEG_INT((byte)0x7b, "neg-int", ReferenceType.none, Format.Format12x),
+ NOT_INT((byte)0x7c, "not-int", ReferenceType.none, Format.Format12x),
+ NEG_LONG((byte)0x7d, "neg-long", ReferenceType.none, Format.Format12x),
+ NOT_LONG((byte)0x7e, "not-long", ReferenceType.none, Format.Format12x),
+ NEG_FLOAT((byte)0x7f, "neg-float", ReferenceType.none, Format.Format12x),
+ NEG_DOUBLE((byte)0x80, "neg-double", ReferenceType.none, Format.Format12x),
+ INT_TO_LONG((byte)0x81, "int-to-long", ReferenceType.none, Format.Format12x),
+ INT_TO_FLOAT((byte)0x82, "int-to-float", ReferenceType.none, Format.Format12x),
+ INT_TO_DOUBLE((byte)0x83, "int-to-double", ReferenceType.none, Format.Format12x),
+ LONG_TO_INT((byte)0x84, "long-to-int", ReferenceType.none, Format.Format12x),
+ LONG_TO_FLOAT((byte)0x85, "long-to-float", ReferenceType.none, Format.Format12x),
+ LONG_TO_DOUBLE((byte)0x86, "long-to-double", ReferenceType.none, Format.Format12x),
+ FLOAT_TO_INT((byte)0x87, "float-to-int", ReferenceType.none, Format.Format12x),
+ FLOAT_TO_LONG((byte)0x88, "float-to-long", ReferenceType.none, Format.Format12x),
+ FLOAT_TO_DOUBLE((byte)0x89, "float-to-double", ReferenceType.none, Format.Format12x),
+ DOUBLE_TO_INT((byte)0x8a, "double-to-int", ReferenceType.none, Format.Format12x),
+ DOUBLE_TO_LONG((byte)0x8b, "double-to-long", ReferenceType.none, Format.Format12x),
+ DOUBLE_TO_FLOAT((byte)0x8c, "double-to-float", ReferenceType.none, Format.Format12x),
+ INT_TO_BYTE((byte)0x8d, "int-to-byte", ReferenceType.none, Format.Format12x),
+ INT_TO_CHAR((byte)0x8e, "int-to-char", ReferenceType.none, Format.Format12x),
+ INT_TO_SHORT((byte)0x8f, "int-to-short", ReferenceType.none, Format.Format12x),
+ ADD_INT((byte)0x90, "add-int", ReferenceType.none, Format.Format23x),
+ SUB_INT((byte)0x91, "sub-int", ReferenceType.none, Format.Format23x),
+ MUL_INT((byte)0x92, "mul-int", ReferenceType.none, Format.Format23x),
+ DIV_INT((byte)0x93, "div-int", ReferenceType.none, Format.Format23x),
+ REM_INT((byte)0x94, "rem-int", ReferenceType.none, Format.Format23x),
+ AND_INT((byte)0x95, "and-int", ReferenceType.none, Format.Format23x),
+ OR_INT((byte)0x96, "or-int", ReferenceType.none, Format.Format23x),
+ XOR_INT((byte)0x97, "xor-int", ReferenceType.none, Format.Format23x),
+ SHL_INT((byte)0x98, "shl-int", ReferenceType.none, Format.Format23x),
+ SHR_INT((byte)0x99, "shr-int", ReferenceType.none, Format.Format23x),
+ USHR_INT((byte)0x9a, "ushr-int", ReferenceType.none, Format.Format23x),
+ ADD_LONG((byte)0x9b, "add-long", ReferenceType.none, Format.Format23x),
+ SUB_LONG((byte)0x9c, "sub-long", ReferenceType.none, Format.Format23x),
+ MUL_LONG((byte)0x9d, "mul-long", ReferenceType.none, Format.Format23x),
+ DIV_LONG((byte)0x9e, "div-long", ReferenceType.none, Format.Format23x),
+ REM_LONG((byte)0x9f, "rem-long", ReferenceType.none, Format.Format23x),
+ AND_LONG((byte)0xa0, "and-long", ReferenceType.none, Format.Format23x),
+ OR_LONG((byte)0xa1, "or-long", ReferenceType.none, Format.Format23x),
+ XOR_LONG((byte)0xa2, "xor-long", ReferenceType.none, Format.Format23x),
+ SHL_LONG((byte)0xa3, "shl-long", ReferenceType.none, Format.Format23x),
+ SHR_LONG((byte)0xa4, "shr-long", ReferenceType.none, Format.Format23x),
+ USHR_LONG((byte)0xa5, "ushr-long", ReferenceType.none, Format.Format23x),
+ ADD_FLOAT((byte)0xa6, "add-float", ReferenceType.none, Format.Format23x),
+ SUB_FLOAT((byte)0xa7, "sub-float", ReferenceType.none, Format.Format23x),
+ MUL_FLOAT((byte)0xa8, "mul-float", ReferenceType.none, Format.Format23x),
+ DIV_FLOAT((byte)0xa9, "div-float", ReferenceType.none, Format.Format23x),
+ REM_FLOAT((byte)0xaa, "rem-float", ReferenceType.none, Format.Format23x),
+ ADD_DOUBLE((byte)0xab, "add-double", ReferenceType.none, Format.Format23x),
+ SUB_DOUBLE((byte)0xac, "sub-double", ReferenceType.none, Format.Format23x),
+ MUL_DOUBLE((byte)0xad, "mul-double", ReferenceType.none, Format.Format23x),
+ DIV_DOUBLE((byte)0xae, "div-double", ReferenceType.none, Format.Format23x),
+ REM_DOUBLE((byte)0xaf, "rem-double", ReferenceType.none, Format.Format23x),
+ ADD_INT_2ADDR((byte)0xb0, "add-int/2addr", ReferenceType.none, Format.Format12x),
+ SUB_INT_2ADDR((byte)0xb1, "sub-int/2addr", ReferenceType.none, Format.Format12x),
+ MUL_INT_2ADDR((byte)0xb2, "mul-int/2addr", ReferenceType.none, Format.Format12x),
+ DIV_INT_2ADDR((byte)0xb3, "div-int/2addr", ReferenceType.none, Format.Format12x),
+ REM_INT_2ADDR((byte)0xb4, "rem-int/2addr", ReferenceType.none, Format.Format12x),
+ AND_INT_2ADDR((byte)0xb5, "and-int/2addr", ReferenceType.none, Format.Format12x),
+ OR_INT_2ADDR((byte)0xb6, "or-int/2addr", ReferenceType.none, Format.Format12x),
+ XOR_INT_2ADDR((byte)0xb7, "xor-int/2addr", ReferenceType.none, Format.Format12x),
+ SHL_INT_2ADDR((byte)0xb8, "shl-int/2addr", ReferenceType.none, Format.Format12x),
+ SHR_INT_2ADDR((byte)0xb9, "shr-int/2addr", ReferenceType.none, Format.Format12x),
+ USHR_INT_2ADDR((byte)0xba, "ushr-int/2addr", ReferenceType.none, Format.Format12x),
+ ADD_LONG_2ADDR((byte)0xbb, "add-long/2addr", ReferenceType.none, Format.Format12x),
+ SUB_LONG_2ADDR((byte)0xbc, "sub-long/2addr", ReferenceType.none, Format.Format12x),
+ MUL_LONG_2ADDR((byte)0xbd, "mul-long/2addr", ReferenceType.none, Format.Format12x),
+ DIV_LONG_2ADDR((byte)0xbe, "div-long/2addr", ReferenceType.none, Format.Format12x),
+ REM_LONG_2ADDR((byte)0xbf, "rem-long/2addr", ReferenceType.none, Format.Format12x),
+ AND_LONG_2ADDR((byte)0xc0, "and-long/2addr", ReferenceType.none, Format.Format12x),
+ OR_LONG_2ADDR((byte)0xc1, "or-long/2addr", ReferenceType.none, Format.Format12x),
+ XOR_LONG_2ADDR((byte)0xc2, "xor-long/2addr", ReferenceType.none, Format.Format12x),
+ SHL_LONG_2ADDR((byte)0xc3, "shl-long/2addr", ReferenceType.none, Format.Format12x),
+ SHR_LONG_2ADDR((byte)0xc4, "shr-long/2addr", ReferenceType.none, Format.Format12x),
+ USHR_LONG_2ADDR((byte)0xc5, "ushr-long/2addr", ReferenceType.none, Format.Format12x),
+ ADD_FLOAT_2ADDR((byte)0xc6, "add-float/2addr", ReferenceType.none, Format.Format12x),
+ SUB_FLOAT_2ADDR((byte)0xc7, "sub-float/2addr", ReferenceType.none, Format.Format12x),
+ MUL_FLOAT_2ADDR((byte)0xc8, "mul-float/2addr", ReferenceType.none, Format.Format12x),
+ DIV_FLOAT_2ADDR((byte)0xc9, "div-float/2addr", ReferenceType.none, Format.Format12x),
+ REM_FLOAT_2ADDR((byte)0xca, "rem-float/2addr", ReferenceType.none, Format.Format12x),
+ ADD_DOUBLE_2ADDR((byte)0xcb, "add-double/2addr", ReferenceType.none, Format.Format12x),
+ SUB_DOUBLE_2ADDR((byte)0xcc, "sub-double/2addr", ReferenceType.none, Format.Format12x),
+ MUL_DOUBLE_2ADDR((byte)0xcd, "mul-double/2addr", ReferenceType.none, Format.Format12x),
+ DIV_DOUBLE_2ADDR((byte)0xce, "div-double/2addr", ReferenceType.none, Format.Format12x),
+ REM_DOUBLE_2ADDR((byte)0xcf, "rem-double/2addr", ReferenceType.none, Format.Format12x),
+ ADD_INT_LIT16((byte)0xd0, "add-int/lit16", ReferenceType.none, Format.Format22s),
+ RSUB_INT((byte)0xd1, "rsub-int", ReferenceType.none, Format.Format22s),
+ MUL_INT_LIT16((byte)0xd2, "mul-int/lit16", ReferenceType.none, Format.Format22s),
+ DIV_INT_LIT16((byte)0xd3, "div-int/lit16", ReferenceType.none, Format.Format22s),
+ REM_INT_LIT16((byte)0xd4, "rem-int/lit16", ReferenceType.none, Format.Format22s),
+ AND_INT_LIT16((byte)0xd5, "and-int/lit16", ReferenceType.none, Format.Format22s),
+ OR_INT_LIT16((byte)0xd6, "or-int/lit16", ReferenceType.none, Format.Format22s),
+ XOR_INT_LIT16((byte)0xd7, "xor-int/lit16", ReferenceType.none, Format.Format22s),
+ ADD_INT_LIT8((byte)0xd8, "add-int/lit8", ReferenceType.none, Format.Format22b),
+ RSUB_INT_LIT8((byte)0xd9, "rsub-int/lit8", ReferenceType.none, Format.Format22b),
+ MUL_INT_LIT8((byte)0xda, "mul-int/lit8", ReferenceType.none, Format.Format22b),
+ DIV_INT_LIT8((byte)0xdb, "div-int/lit8", ReferenceType.none, Format.Format22b),
+ REM_INT_LIT8((byte)0xdc, "rem-int/lit8", ReferenceType.none, Format.Format22b),
+ AND_INT_LIT8((byte)0xdd, "and-int/lit8", ReferenceType.none, Format.Format22b),
+ OR_INT_LIT8((byte)0xde, "or-int/lit8", ReferenceType.none, Format.Format22b),
+ XOR_INT_LIT8((byte)0xdf, "xor-int/lit8", ReferenceType.none, Format.Format22b),
+ SHL_INT_LIT8((byte)0xe0, "shl-int/lit8", ReferenceType.none, Format.Format22b),
+ SHR_INT_LIT8((byte)0xe1, "shr-int/lit8", ReferenceType.none, Format.Format22b),
+ USHR_INT_LIT8((byte)0xe2, "ushr-int/lit8", ReferenceType.none, Format.Format22b),
+
+
+ INVOKE_EXECUTE_INLINE((byte)0xee, "execute_inline", ReferenceType.none, Format.Format35ms, true),
+ INVOKE_DIRECT_EMPTY((byte)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35s, true),
+ IGET_QUICK((byte)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, true),
+ IGET_WIDE_QUICK((byte)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, true),
+ IGET_OBJECT_QUICK((byte)0xf4, "iget-object-quick", ReferenceType.none, Format.Format22cs, true),
+ IPUT_QUICK((byte)0xf5, "iput-quick", ReferenceType.none, Format.Format22cs, true),
+ IPUT_WIDE_QUICK((byte)0xf6, "iput-wide-quick", ReferenceType.none, Format.Format22cs, true),
+ IPUT_OBJECT_QUICK((byte)0xf7, "iput-object-quick", ReferenceType.none, Format.Format22cs, true),
+ INVOKE_VIRTUAL_QUICK((byte)0xf8, "invoke-virtual-quick", ReferenceType.none, Format.Format35ms, true),
+ INVOKE_VIRTUAL_RANGE_QUICK((byte)0xf9, "invoke-virtual-range-quick", ReferenceType.none, Format.Format3rms, true),
+ INVOKE_SUPER_QUICK((byte)0xfa, "invoke-super-quick", ReferenceType.none, Format.Format35ms, true),
+ INVOKE_SUPER_RANGE_QUICK((byte)0xfb, "invoke-super-range-quick", ReferenceType.none, Format.Format3rms, true);
+
+
+
+ private static Opcode[] opcodesByValue;
+ private static HashMap opcodesByName;
+
+ static {
+ opcodesByValue = new Opcode[256];
+ opcodesByName = new HashMap();
+
+ for (Opcode opcode: Opcode.values()) {
+ opcodesByValue[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(byte opcodeValue) {
+ return opcodesByValue[opcodeValue & 0xFF];
+ }
+
+ public final byte value;
+ public final String name;
+ public final ReferenceType referenceType;
+ public final Format format;
+ public final boolean odexOnly;
+
+ Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format) {
+ this(opcodeValue, opcodeName, referenceType, format, false);
+ }
+
+ Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format, boolean odexOnly) {
+ this.value = opcodeValue;
+ this.name = opcodeName;
+ this.referenceType = referenceType;
+ this.format = format;
+ this.odexOnly = odexOnly;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/ReferenceType.java b/dexlib/src/main/java/org/jf/dexlib/Code/ReferenceType.java
index 8590dae3..9ba9a50a 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Code/ReferenceType.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Code/ReferenceType.java
@@ -1,56 +1,56 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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 org.jf.dexlib.*;
-
-public enum ReferenceType
-{
- string,
- type,
- field,
- method,
- none;
-
- 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;
- case none:
- return item == null;
- }
- return false;
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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 org.jf.dexlib.*;
+
+public enum ReferenceType
+{
+ string,
+ type,
+ field,
+ method,
+ none;
+
+ 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;
+ case none:
+ return item == null;
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java
index 8d2f7ba2..9e04d8ba 100644
--- a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java
@@ -1,712 +1,712 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Code.*;
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.SparseArray;
-import org.jf.dexlib.Util.Leb128Utils;
-
-import java.util.List;
-import java.util.LinkedList;
-
-public class CodeItem extends Item {
- private int registerCount;
- private int inWords;
- private int outWords;
- private DebugInfoItem debugInfo;
- private byte[] encodedInstructions;
- private Item[] referencedItems;
- private TryItem[] tries;
- private EncodedCatchHandler[] encodedCatchHandlers;
-
- private ClassDataItem.EncodedMethod parent;
-
- /**
- * Creates a new uninitialized CodeItem
- * @param dexFile The DexFile
that this item belongs to
- */
- public CodeItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new CodeItem
with the given values.
- * @param dexFile The DexFile
that this item belongs to
- * @param registerCount the number of registers that the method containing this code uses
- * @param inWords the number of 2-byte words that the parameters to the method containing this code take
- * @param outWords the maximum number of 2-byte words for the arguments of any method call in this code
- * @param debugInfo the debug information for this code/method
- * @param encodedInstructions the instructions, encoded as a byte array
- * @param referencedItems an array of the items referenced by instructions, in order of occurance in the code
- * @param tries an array of the tries defined for this code/method
- * @param encodedCatchHandlers an array of the exception handlers defined for this code/method
- */
- private CodeItem(DexFile dexFile,
- int registerCount,
- int inWords,
- int outWords,
- DebugInfoItem debugInfo,
- byte[] encodedInstructions,
- Item[] referencedItems,
- TryItem[] tries,
- EncodedCatchHandler[] encodedCatchHandlers) {
- super(dexFile);
-
- this.registerCount = registerCount;
- this.inWords = inWords;
- this.outWords = outWords;
- this.debugInfo = debugInfo;
- if (debugInfo != null) {
- debugInfo.setParent(this);
- }
- this.encodedInstructions = encodedInstructions;
- this.referencedItems = referencedItems;
- this.tries = tries;
- this.encodedCatchHandlers = encodedCatchHandlers;
- }
-
- /**
- * Returns a new CodeItem
with the given values.
- * @param dexFile The DexFile
that this item belongs to
- * @param registerCount the number of registers that the method containing this code uses
- * @param inWords the number of 2-byte words that the parameters to the method containing this code take
- * @param outWords the maximum number of 2-byte words for the arguments of any method call in this code
- * @param debugInfo the debug information for this code/method
- * @param encodedInstructions the instructions, encoded as a byte array
- * @param referencedItems a list of the items referenced by instructions, in order of occurance in the code,
- * or null if none
- * @param tries a list of the tries defined for this code/method or null if none
- * @param encodedCatchHandlers a list of the exception handlers defined for this code/method or null if none
- * @return a new CodeItem
with the given values.
- */
- public static CodeItem getInternedCodeItem(DexFile dexFile,
- int registerCount,
- int inWords,
- int outWords,
- DebugInfoItem debugInfo,
- byte[] encodedInstructions,
- List- referencedItems,
- List tries,
- List encodedCatchHandlers) {
- Item[] referencedItemsArray = null;
- TryItem[] triesArray = null;
- EncodedCatchHandler[] encodedCatchHandlersArray = null;
-
- if (referencedItems != null && referencedItems.size() > 0) {
- referencedItemsArray = new Item[referencedItems.size()];
- referencedItems.toArray(referencedItemsArray);
- }
-
- if (tries != null && tries.size() > 0) {
- triesArray = new TryItem[tries.size()];
- tries.toArray(triesArray);
- }
-
- if (encodedCatchHandlers != null && encodedCatchHandlers.size() > 0) {
- encodedCatchHandlersArray = new EncodedCatchHandler[encodedCatchHandlers.size()];
- encodedCatchHandlers.toArray(encodedCatchHandlersArray);
- }
-
- CodeItem codeItem = new CodeItem(dexFile, registerCount, inWords, outWords, debugInfo, encodedInstructions,
- referencedItemsArray, triesArray, encodedCatchHandlersArray);
- return dexFile.CodeItemsSection.intern(codeItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- this.registerCount = in.readShort();
- this.inWords = in.readShort();
- this.outWords = in.readShort();
- int triesCount = in.readShort();
- this.debugInfo = (DebugInfoItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_DEBUG_INFO_ITEM,
- in.readInt());
- if (this.debugInfo != null) {
- this.debugInfo.setParent(this);
- }
- int instructionCount = in.readInt();
- this.encodedInstructions = in.readBytes(instructionCount * 2);
- this.referencedItems = InstructionReader.getReferencedItems(encodedInstructions, dexFile);
- if (triesCount > 0) {
- in.alignTo(4);
-
- //we need to read in the catch handlers first, so save the offset to the try items for future reference
- int triesOffset = in.getCursor();
- in.setCursor(triesOffset + 8 * triesCount);
-
- //read in the encoded catch handlers
- int encodedHandlerStart = in.getCursor();
- int handlerCount = in.readUnsignedLeb128();
- SparseArray handlerMap = new SparseArray(handlerCount);
- encodedCatchHandlers = new EncodedCatchHandler[handlerCount];
- for (int i=0; i 0) {
- if (encodedInstructions.length % 4 != 0) {
- offset+=2;
- }
-
- offset += tries.length * 8;
- int encodedCatchHandlerBaseOffset = offset;
- offset += Leb128Utils.unsignedLeb128Size(encodedCatchHandlers.length);
- for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
- offset = encodedCatchHandler.place(offset, encodedCatchHandlerBaseOffset);
- }
- }
- return offset;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(final AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(0, parent.method.getMethodString());
- out.annotate(2, "registers_size: 0x" + Integer.toHexString(registerCount) + " (" + registerCount + ")");
- out.annotate(2, "ins_size: 0x" + Integer.toHexString(inWords) + " (" + inWords + ")");
- out.annotate(2, "outs_size: 0x" + Integer.toHexString(outWords) + " (" + outWords + ")");
- int triesLength = tries==null?0:tries.length;
- out.annotate(2, "tries_size: 0x" + Integer.toHexString(triesLength) + " (" + triesLength + ")");
- if (debugInfo == null) {
- out.annotate(4, "debug_info_off:");
- } else {
- out.annotate(4, "debug_info_off: 0x" + debugInfo.getOffset());
- }
- out.annotate(4, "insns_size: 0x" + Integer.toHexString(encodedInstructions.length / 2) + " (" +
- (encodedInstructions.length / 2) + ")");
- InstructionIterator.IterateInstructions(encodedInstructions,
- new InstructionIterator.ProcessRawInstructionDelegate() {
-
- public void ProcessNormalInstruction(Opcode opcode, int index) {
- out.annotate(opcode.format.size, "[0x" + Integer.toHexString(index/2) + "] " + opcode.name +
- " instruction");
- }
-
- public void ProcessReferenceInstruction(Opcode opcode, int index) {
- out.annotate(opcode.format.size, "[0x" + Integer.toHexString(index/2) + "] " + opcode.name +
- " instruction");
- }
-
- public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength) {
- out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " +
- "packed_switch instruction");
- }
-
- public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength) {
- out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " +
- "sparse_switch instruction");
- }
-
- public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount,
- int instructionLength) {
- out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " +
- "fill_array_data instruction");
- }
- });
- }
-
- out.writeShort(registerCount);
- out.writeShort(inWords);
- out.writeShort(outWords);
- if (tries == null) {
- out.writeShort(0);
- } else {
- out.writeShort(tries.length);
- }
- if (debugInfo == null) {
- out.writeInt(0);
- } else {
- out.writeInt(debugInfo.getOffset());
- }
- out.writeInt(encodedInstructions.length / 2);
- InstructionWriter.writeInstructions(encodedInstructions, referencedItems, out);
-
- if (tries != null && tries.length > 0) {
- if (out.annotates()) {
- if ((encodedInstructions.length % 4) != 0) {
- out.annotate("padding");
- out.writeShort(0);
- }
-
- int index = 0;
- for (TryItem tryItem: tries) {
- out.annotate(0, "[0x" + Integer.toHexString(index++) + "] try_item");
- out.indent();
- tryItem.writeTo(out);
- out.deindent();
- }
-
- out.annotate("handler_count: 0x" + Integer.toHexString(encodedCatchHandlers.length) + "(" +
- encodedCatchHandlers.length + ")");
- out.writeUnsignedLeb128(encodedCatchHandlers.length);
-
- index = 0;
- for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
- out.annotate(0, "[" + Integer.toHexString(index++) + "] encoded_catch_handler");
- out.indent();
- encodedCatchHandler.writeTo(out);
- out.deindent();
- }
- } else {
- if ((encodedInstructions.length % 4) != 0) {
- out.writeShort(0);
- }
-
- for (TryItem tryItem: tries) {
- tryItem.writeTo(out);
- }
-
- out.writeUnsignedLeb128(encodedCatchHandlers.length);
-
- for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
- encodedCatchHandler.writeTo(out);
- }
- }
- }
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_CODE_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- //TODO: should mention the method name here
- return "code_item @0x" + Integer.toHexString(getOffset());
- }
-
- /** {@inheritDoc} */
- public int compareTo(CodeItem other) {
- if (parent == null) {
- if (other.parent == null) {
- return 0;
- }
- return -1;
- }
- if (other.parent == null) {
- return 1;
- }
- return parent.method.compareTo(other.parent.method);
- }
-
- /**
- * @return the register count
- */
- public int getRegisterCount() {
- return registerCount;
- }
-
- /**
- * @return a byte array containing the encoded instructions
- */
- public byte[] getEncodedInstructions() {
- return encodedInstructions;
- }
-
- /**
- * @return an array of the
TryItem
objects in this CodeItem
- */
- public TryItem[] getTries() {
- return tries;
- }
-
- /**
- * @return an array of the EncodedCatchHandler
objects in this CodeItem
- */
- public EncodedCatchHandler[] getHandlers() {
- return encodedCatchHandlers;
- }
-
- /**
- * @return the DebugInfoItem
associated with this CodeItem
- */
- public DebugInfoItem getDebugInfo() {
- return debugInfo;
- }
-
- /**
- * Sets the MethodIdItem
of the method that this CodeItem
is associated with
- * @param encodedMethod the EncodedMethod
of the method that this CodeItem
is associated
- * with
- */
- protected void setParent(ClassDataItem.EncodedMethod encodedMethod) {
- this.parent = encodedMethod;
- }
-
- /**
- * @return the MethodIdItem of the method that this CodeItem belongs to
- */
- public ClassDataItem.EncodedMethod getParent() {
- return parent;
- }
-
- /**
- * Used by OdexUtil to update this CodeItem
with a deodexed version of the instructions
- * @param newEncodedInstructions
- */
- public void updateCode(byte[] newEncodedInstructions) {
- final LinkedList- referencedItemsList = new LinkedList
- ();
-
-
- InstructionIterator.IterateInstructions(dexFile, newEncodedInstructions,
- new InstructionIterator.ProcessInstructionDelegate() {
- public void ProcessInstruction(int index, Instruction instruction) {
- if (instruction.opcode.referenceType != ReferenceType.none) {
- referencedItemsList.add(((InstructionWithReference)instruction).getReferencedItem());
- }
- }
- });
-
- referencedItems = new Item[referencedItemsList.size()];
- referencedItemsList.toArray(referencedItems);
- encodedInstructions = newEncodedInstructions;
- }
-
- public static class TryItem {
- /**
- * The address (in 2-byte words) within the code where the try block starts
- */
- public final int startAddress;
-
- /**
- * The number of 2-byte words that the try block covers
- */
- public final int instructionCount;
-
- /**
- * The associated exception handler
- */
- public final EncodedCatchHandler encodedCatchHandler;
-
- /**
- * Construct a new
TryItem
with the given values
- * @param startAddress the address (in 2-byte words) within the code where the try block starts
- * @param instructionCount the number of 2-byte words that the try block covers
- * @param encodedCatchHandler the associated exception handler
- */
- public TryItem(int startAddress, int instructionCount, EncodedCatchHandler encodedCatchHandler) {
- this.startAddress = startAddress;
- this.instructionCount = instructionCount;
- this.encodedCatchHandler = encodedCatchHandler;
- }
-
- /**
- * This is used internally to construct a new TryItem
while reading in a DexFile
- * @param in the Input object to read the TryItem
from
- * @param encodedCatchHandlers a SparseArray of the EncodedCatchHandlers for this CodeItem
. The
- * key should be the offset of the EncodedCatchHandler from the beginning of the encoded_catch_handler_list
- * structure.
- */
- private TryItem(Input in, SparseArray encodedCatchHandlers) {
- startAddress = in.readInt();
- instructionCount = in.readShort();
-
- encodedCatchHandler = encodedCatchHandlers.get(in.readShort());
- if (encodedCatchHandler == null) {
- throw new RuntimeException("Could not find the EncodedCatchHandler referenced by this TryItem");
- }
- }
-
- /**
- * Writes the TryItem
to the given AnnotatedOutput
object
- * @param out the AnnotatedOutput
object to write to
- */
- private void writeTo(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(4, "start_addr: 0x" + Integer.toHexString(startAddress));
- out.annotate(2, "insn_count: 0x" + Integer.toHexString(instructionCount) + " (" + instructionCount +
- ")");
- out.annotate(2, "handler_off: 0x" + Integer.toHexString(encodedCatchHandler.getOffsetInList()));
- }
-
- out.writeInt(startAddress);
- out.writeShort(instructionCount);
- out.writeShort(encodedCatchHandler.getOffsetInList());
- }
- }
-
- public static class EncodedCatchHandler {
- /**
- * An array of the individual exception handlers
- */
- public final EncodedTypeAddrPair[] handlers;
-
- /**
- * The address within the code (in 2-byte words) for the catch all handler, or -1 if there is no catch all
- * handler
- */
- public final int catchAllHandlerAddress;
-
- //TODO: would it be possible to get away without having these? and generate/create these values while writing?
- private int baseOffset;
- private int offset;
-
- /**
- * Constructs a new EncodedCatchHandler
with the given values
- * @param handlers an array of the individual exception handlers
- * @param catchAllHandlerAddress The address within the code (in 2-byte words) for the catch all handler, or -1
- * if there is no catch all handler
- */
- public EncodedCatchHandler(EncodedTypeAddrPair[] handlers, int catchAllHandlerAddress) {
- this.handlers = handlers;
- this.catchAllHandlerAddress = catchAllHandlerAddress;
- }
-
- /**
- * This is used internally to construct a new EncodedCatchHandler
while reading in a
- * DexFile
- * @param dexFile the DexFile
that is being read in
- * @param in the Input object to read the EncodedCatchHandler
from
- */
- private EncodedCatchHandler(DexFile dexFile, Input in) {
- int handlerCount = in.readSignedLeb128();
-
- if (handlerCount < 0) {
- handlers = new EncodedTypeAddrPair[-1 * handlerCount];
- } else {
- handlers = new EncodedTypeAddrPair[handlerCount];
- }
-
- for (int i=0; iEncodedCatchHandler from the beginning of the
- * encoded_catch_handler_list structure
- */
- private int getOffsetInList() {
- return offset-baseOffset;
- }
-
- /**
- * Places the EncodedCatchHandler
, storing the offset and baseOffset, and returning the offset
- * immediately following this EncodedCatchHandler
- * @param offset the offset of this EncodedCatchHandler
in the DexFile
- * @param baseOffset the offset of the beginning of the encoded_catch_handler_list structure in the
- * DexFile
- * @return the offset immediately following this EncodedCatchHandler
- */
- private int place(int offset, int baseOffset) {
- this.offset = offset;
- this.baseOffset = baseOffset;
-
- int size = handlers.length;
- if (catchAllHandlerAddress > -1) {
- size *= -1;
- offset += Leb128Utils.unsignedLeb128Size(catchAllHandlerAddress);
- }
- offset += Leb128Utils.signedLeb128Size(size);
-
- for (EncodedTypeAddrPair handler: handlers) {
- offset += handler.getSize();
- }
- return offset;
- }
-
- /**
- * Writes the EncodedCatchHandler
to the given AnnotatedOutput
object
- * @param out the AnnotatedOutput
object to write to
- */
- private void writeTo(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate("size: 0x" + Integer.toHexString(handlers.length) + " (" + handlers.length + ")");
-
- int size = handlers.length;
- if (catchAllHandlerAddress > -1) {
- size = size * -1;
- }
- out.writeSignedLeb128(size);
-
- int index = 0;
- for (EncodedTypeAddrPair handler: handlers) {
- out.annotate(0, "[" + index++ + "] encoded_type_addr_pair");
- out.indent();
- handler.writeTo(out);
- out.deindent();
- }
-
- if (catchAllHandlerAddress > -1) {
- out.annotate("catch_all_addr: 0x" + Integer.toHexString(catchAllHandlerAddress));
- out.writeUnsignedLeb128(catchAllHandlerAddress);
- }
- } else {
- int size = handlers.length;
- if (catchAllHandlerAddress > -1) {
- size = size * -1;
- }
- out.writeSignedLeb128(size);
-
- for (EncodedTypeAddrPair handler: handlers) {
- handler.writeTo(out);
- }
-
- if (catchAllHandlerAddress > -1) {
- out.writeUnsignedLeb128(catchAllHandlerAddress);
- }
- }
- }
-
- @Override
- public int hashCode() {
- int hash = 0;
- for (EncodedTypeAddrPair handler: handlers) {
- hash = hash * 31 + handler.hashCode();
- }
- hash = hash * 31 + catchAllHandlerAddress;
- return hash;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this==o) {
- return true;
- }
- if (o==null || !this.getClass().equals(o.getClass())) {
- return false;
- }
-
- EncodedCatchHandler other = (EncodedCatchHandler)o;
- if (handlers.length != other.handlers.length || catchAllHandlerAddress != other.catchAllHandlerAddress) {
- return false;
- }
-
- for (int i=0; iException that this handler handles
- */
- public final TypeIdItem exceptionType;
-
- /**
- * The address (in 2-byte words) in the code of the handler
- */
- public final int handlerAddress;
-
- /**
- * Constructs a new EncodedTypeAddrPair
with the given values
- * @param exceptionType the type of the Exception
that this handler handles
- * @param handlerAddress the address (in 2-byte words) in the code of the handler
- */
- public EncodedTypeAddrPair(TypeIdItem exceptionType, int handlerAddress) {
- this.exceptionType = exceptionType;
- this.handlerAddress = handlerAddress;
- }
-
- /**
- * This is used internally to construct a new EncodedTypeAddrPair
while reading in a
- * DexFile
- * @param dexFile the DexFile
that is being read in
- * @param in the Input object to read the EncodedCatchHandler
from
- */
- private EncodedTypeAddrPair(DexFile dexFile, Input in) {
- exceptionType = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128());
- handlerAddress = in.readUnsignedLeb128();
- }
-
- /**
- * @return the size of this EncodedTypeAddrPair
- */
- private int getSize() {
- return Leb128Utils.unsignedLeb128Size(exceptionType.getIndex()) +
- Leb128Utils.unsignedLeb128Size(handlerAddress);
- }
-
- /**
- * Writes the EncodedTypeAddrPair
to the given AnnotatedOutput
object
- * @param out the AnnotatedOutput
object to write to
- */
- private void writeTo(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate("exception_type: " + exceptionType.getTypeDescriptor());
- out.writeUnsignedLeb128(exceptionType.getIndex());
-
- out.annotate("handler_addr: 0x" + Integer.toHexString(handlerAddress));
- out.writeUnsignedLeb128(handlerAddress);
- } else {
- out.writeUnsignedLeb128(exceptionType.getIndex());
- out.writeUnsignedLeb128(handlerAddress);
- }
- }
-
- @Override
- public int hashCode() {
- return exceptionType.hashCode() * 31 + handlerAddress;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this==o) {
- return true;
- }
- if (o==null || !this.getClass().equals(o.getClass())) {
- return false;
- }
-
- EncodedTypeAddrPair other = (EncodedTypeAddrPair)o;
- return exceptionType == other.exceptionType && handlerAddress == other.handlerAddress;
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Code.*;
+import org.jf.dexlib.Util.AnnotatedOutput;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.SparseArray;
+import org.jf.dexlib.Util.Leb128Utils;
+
+import java.util.List;
+import java.util.LinkedList;
+
+public class CodeItem extends Item {
+ private int registerCount;
+ private int inWords;
+ private int outWords;
+ private DebugInfoItem debugInfo;
+ private byte[] encodedInstructions;
+ private Item[] referencedItems;
+ private TryItem[] tries;
+ private EncodedCatchHandler[] encodedCatchHandlers;
+
+ private ClassDataItem.EncodedMethod parent;
+
+ /**
+ * Creates a new uninitialized CodeItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ public CodeItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new CodeItem
with the given values.
+ * @param dexFile The DexFile
that this item belongs to
+ * @param registerCount the number of registers that the method containing this code uses
+ * @param inWords the number of 2-byte words that the parameters to the method containing this code take
+ * @param outWords the maximum number of 2-byte words for the arguments of any method call in this code
+ * @param debugInfo the debug information for this code/method
+ * @param encodedInstructions the instructions, encoded as a byte array
+ * @param referencedItems an array of the items referenced by instructions, in order of occurance in the code
+ * @param tries an array of the tries defined for this code/method
+ * @param encodedCatchHandlers an array of the exception handlers defined for this code/method
+ */
+ private CodeItem(DexFile dexFile,
+ int registerCount,
+ int inWords,
+ int outWords,
+ DebugInfoItem debugInfo,
+ byte[] encodedInstructions,
+ Item[] referencedItems,
+ TryItem[] tries,
+ EncodedCatchHandler[] encodedCatchHandlers) {
+ super(dexFile);
+
+ this.registerCount = registerCount;
+ this.inWords = inWords;
+ this.outWords = outWords;
+ this.debugInfo = debugInfo;
+ if (debugInfo != null) {
+ debugInfo.setParent(this);
+ }
+ this.encodedInstructions = encodedInstructions;
+ this.referencedItems = referencedItems;
+ this.tries = tries;
+ this.encodedCatchHandlers = encodedCatchHandlers;
+ }
+
+ /**
+ * Returns a new CodeItem
with the given values.
+ * @param dexFile The DexFile
that this item belongs to
+ * @param registerCount the number of registers that the method containing this code uses
+ * @param inWords the number of 2-byte words that the parameters to the method containing this code take
+ * @param outWords the maximum number of 2-byte words for the arguments of any method call in this code
+ * @param debugInfo the debug information for this code/method
+ * @param encodedInstructions the instructions, encoded as a byte array
+ * @param referencedItems a list of the items referenced by instructions, in order of occurance in the code,
+ * or null if none
+ * @param tries a list of the tries defined for this code/method or null if none
+ * @param encodedCatchHandlers a list of the exception handlers defined for this code/method or null if none
+ * @return a new CodeItem
with the given values.
+ */
+ public static CodeItem getInternedCodeItem(DexFile dexFile,
+ int registerCount,
+ int inWords,
+ int outWords,
+ DebugInfoItem debugInfo,
+ byte[] encodedInstructions,
+ List- referencedItems,
+ List tries,
+ List encodedCatchHandlers) {
+ Item[] referencedItemsArray = null;
+ TryItem[] triesArray = null;
+ EncodedCatchHandler[] encodedCatchHandlersArray = null;
+
+ if (referencedItems != null && referencedItems.size() > 0) {
+ referencedItemsArray = new Item[referencedItems.size()];
+ referencedItems.toArray(referencedItemsArray);
+ }
+
+ if (tries != null && tries.size() > 0) {
+ triesArray = new TryItem[tries.size()];
+ tries.toArray(triesArray);
+ }
+
+ if (encodedCatchHandlers != null && encodedCatchHandlers.size() > 0) {
+ encodedCatchHandlersArray = new EncodedCatchHandler[encodedCatchHandlers.size()];
+ encodedCatchHandlers.toArray(encodedCatchHandlersArray);
+ }
+
+ CodeItem codeItem = new CodeItem(dexFile, registerCount, inWords, outWords, debugInfo, encodedInstructions,
+ referencedItemsArray, triesArray, encodedCatchHandlersArray);
+ return dexFile.CodeItemsSection.intern(codeItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ this.registerCount = in.readShort();
+ this.inWords = in.readShort();
+ this.outWords = in.readShort();
+ int triesCount = in.readShort();
+ this.debugInfo = (DebugInfoItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_DEBUG_INFO_ITEM,
+ in.readInt());
+ if (this.debugInfo != null) {
+ this.debugInfo.setParent(this);
+ }
+ int instructionCount = in.readInt();
+ this.encodedInstructions = in.readBytes(instructionCount * 2);
+ this.referencedItems = InstructionReader.getReferencedItems(encodedInstructions, dexFile);
+ if (triesCount > 0) {
+ in.alignTo(4);
+
+ //we need to read in the catch handlers first, so save the offset to the try items for future reference
+ int triesOffset = in.getCursor();
+ in.setCursor(triesOffset + 8 * triesCount);
+
+ //read in the encoded catch handlers
+ int encodedHandlerStart = in.getCursor();
+ int handlerCount = in.readUnsignedLeb128();
+ SparseArray handlerMap = new SparseArray(handlerCount);
+ encodedCatchHandlers = new EncodedCatchHandler[handlerCount];
+ for (int i=0; i 0) {
+ if (encodedInstructions.length % 4 != 0) {
+ offset+=2;
+ }
+
+ offset += tries.length * 8;
+ int encodedCatchHandlerBaseOffset = offset;
+ offset += Leb128Utils.unsignedLeb128Size(encodedCatchHandlers.length);
+ for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
+ offset = encodedCatchHandler.place(offset, encodedCatchHandlerBaseOffset);
+ }
+ }
+ return offset;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(final AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(0, parent.method.getMethodString());
+ out.annotate(2, "registers_size: 0x" + Integer.toHexString(registerCount) + " (" + registerCount + ")");
+ out.annotate(2, "ins_size: 0x" + Integer.toHexString(inWords) + " (" + inWords + ")");
+ out.annotate(2, "outs_size: 0x" + Integer.toHexString(outWords) + " (" + outWords + ")");
+ int triesLength = tries==null?0:tries.length;
+ out.annotate(2, "tries_size: 0x" + Integer.toHexString(triesLength) + " (" + triesLength + ")");
+ if (debugInfo == null) {
+ out.annotate(4, "debug_info_off:");
+ } else {
+ out.annotate(4, "debug_info_off: 0x" + debugInfo.getOffset());
+ }
+ out.annotate(4, "insns_size: 0x" + Integer.toHexString(encodedInstructions.length / 2) + " (" +
+ (encodedInstructions.length / 2) + ")");
+ InstructionIterator.IterateInstructions(encodedInstructions,
+ new InstructionIterator.ProcessRawInstructionDelegate() {
+
+ public void ProcessNormalInstruction(Opcode opcode, int index) {
+ out.annotate(opcode.format.size, "[0x" + Integer.toHexString(index/2) + "] " + opcode.name +
+ " instruction");
+ }
+
+ public void ProcessReferenceInstruction(Opcode opcode, int index) {
+ out.annotate(opcode.format.size, "[0x" + Integer.toHexString(index/2) + "] " + opcode.name +
+ " instruction");
+ }
+
+ public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength) {
+ out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " +
+ "packed_switch instruction");
+ }
+
+ public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength) {
+ out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " +
+ "sparse_switch instruction");
+ }
+
+ public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount,
+ int instructionLength) {
+ out.annotate(instructionLength, "[0x" + Integer.toHexString(index/2) + "] " +
+ "fill_array_data instruction");
+ }
+ });
+ }
+
+ out.writeShort(registerCount);
+ out.writeShort(inWords);
+ out.writeShort(outWords);
+ if (tries == null) {
+ out.writeShort(0);
+ } else {
+ out.writeShort(tries.length);
+ }
+ if (debugInfo == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(debugInfo.getOffset());
+ }
+ out.writeInt(encodedInstructions.length / 2);
+ InstructionWriter.writeInstructions(encodedInstructions, referencedItems, out);
+
+ if (tries != null && tries.length > 0) {
+ if (out.annotates()) {
+ if ((encodedInstructions.length % 4) != 0) {
+ out.annotate("padding");
+ out.writeShort(0);
+ }
+
+ int index = 0;
+ for (TryItem tryItem: tries) {
+ out.annotate(0, "[0x" + Integer.toHexString(index++) + "] try_item");
+ out.indent();
+ tryItem.writeTo(out);
+ out.deindent();
+ }
+
+ out.annotate("handler_count: 0x" + Integer.toHexString(encodedCatchHandlers.length) + "(" +
+ encodedCatchHandlers.length + ")");
+ out.writeUnsignedLeb128(encodedCatchHandlers.length);
+
+ index = 0;
+ for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
+ out.annotate(0, "[" + Integer.toHexString(index++) + "] encoded_catch_handler");
+ out.indent();
+ encodedCatchHandler.writeTo(out);
+ out.deindent();
+ }
+ } else {
+ if ((encodedInstructions.length % 4) != 0) {
+ out.writeShort(0);
+ }
+
+ for (TryItem tryItem: tries) {
+ tryItem.writeTo(out);
+ }
+
+ out.writeUnsignedLeb128(encodedCatchHandlers.length);
+
+ for (EncodedCatchHandler encodedCatchHandler: encodedCatchHandlers) {
+ encodedCatchHandler.writeTo(out);
+ }
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_CODE_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ //TODO: should mention the method name here
+ return "code_item @0x" + Integer.toHexString(getOffset());
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(CodeItem other) {
+ if (parent == null) {
+ if (other.parent == null) {
+ return 0;
+ }
+ return -1;
+ }
+ if (other.parent == null) {
+ return 1;
+ }
+ return parent.method.compareTo(other.parent.method);
+ }
+
+ /**
+ * @return the register count
+ */
+ public int getRegisterCount() {
+ return registerCount;
+ }
+
+ /**
+ * @return a byte array containing the encoded instructions
+ */
+ public byte[] getEncodedInstructions() {
+ return encodedInstructions;
+ }
+
+ /**
+ * @return an array of the
TryItem
objects in this CodeItem
+ */
+ public TryItem[] getTries() {
+ return tries;
+ }
+
+ /**
+ * @return an array of the EncodedCatchHandler
objects in this CodeItem
+ */
+ public EncodedCatchHandler[] getHandlers() {
+ return encodedCatchHandlers;
+ }
+
+ /**
+ * @return the DebugInfoItem
associated with this CodeItem
+ */
+ public DebugInfoItem getDebugInfo() {
+ return debugInfo;
+ }
+
+ /**
+ * Sets the MethodIdItem
of the method that this CodeItem
is associated with
+ * @param encodedMethod the EncodedMethod
of the method that this CodeItem
is associated
+ * with
+ */
+ protected void setParent(ClassDataItem.EncodedMethod encodedMethod) {
+ this.parent = encodedMethod;
+ }
+
+ /**
+ * @return the MethodIdItem of the method that this CodeItem belongs to
+ */
+ public ClassDataItem.EncodedMethod getParent() {
+ return parent;
+ }
+
+ /**
+ * Used by OdexUtil to update this CodeItem
with a deodexed version of the instructions
+ * @param newEncodedInstructions
+ */
+ public void updateCode(byte[] newEncodedInstructions) {
+ final LinkedList- referencedItemsList = new LinkedList
- ();
+
+
+ InstructionIterator.IterateInstructions(dexFile, newEncodedInstructions,
+ new InstructionIterator.ProcessInstructionDelegate() {
+ public void ProcessInstruction(int index, Instruction instruction) {
+ if (instruction.opcode.referenceType != ReferenceType.none) {
+ referencedItemsList.add(((InstructionWithReference)instruction).getReferencedItem());
+ }
+ }
+ });
+
+ referencedItems = new Item[referencedItemsList.size()];
+ referencedItemsList.toArray(referencedItems);
+ encodedInstructions = newEncodedInstructions;
+ }
+
+ public static class TryItem {
+ /**
+ * The address (in 2-byte words) within the code where the try block starts
+ */
+ public final int startAddress;
+
+ /**
+ * The number of 2-byte words that the try block covers
+ */
+ public final int instructionCount;
+
+ /**
+ * The associated exception handler
+ */
+ public final EncodedCatchHandler encodedCatchHandler;
+
+ /**
+ * Construct a new
TryItem
with the given values
+ * @param startAddress the address (in 2-byte words) within the code where the try block starts
+ * @param instructionCount the number of 2-byte words that the try block covers
+ * @param encodedCatchHandler the associated exception handler
+ */
+ public TryItem(int startAddress, int instructionCount, EncodedCatchHandler encodedCatchHandler) {
+ this.startAddress = startAddress;
+ this.instructionCount = instructionCount;
+ this.encodedCatchHandler = encodedCatchHandler;
+ }
+
+ /**
+ * This is used internally to construct a new TryItem
while reading in a DexFile
+ * @param in the Input object to read the TryItem
from
+ * @param encodedCatchHandlers a SparseArray of the EncodedCatchHandlers for this CodeItem
. The
+ * key should be the offset of the EncodedCatchHandler from the beginning of the encoded_catch_handler_list
+ * structure.
+ */
+ private TryItem(Input in, SparseArray encodedCatchHandlers) {
+ startAddress = in.readInt();
+ instructionCount = in.readShort();
+
+ encodedCatchHandler = encodedCatchHandlers.get(in.readShort());
+ if (encodedCatchHandler == null) {
+ throw new RuntimeException("Could not find the EncodedCatchHandler referenced by this TryItem");
+ }
+ }
+
+ /**
+ * Writes the TryItem
to the given AnnotatedOutput
object
+ * @param out the AnnotatedOutput
object to write to
+ */
+ private void writeTo(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(4, "start_addr: 0x" + Integer.toHexString(startAddress));
+ out.annotate(2, "insn_count: 0x" + Integer.toHexString(instructionCount) + " (" + instructionCount +
+ ")");
+ out.annotate(2, "handler_off: 0x" + Integer.toHexString(encodedCatchHandler.getOffsetInList()));
+ }
+
+ out.writeInt(startAddress);
+ out.writeShort(instructionCount);
+ out.writeShort(encodedCatchHandler.getOffsetInList());
+ }
+ }
+
+ public static class EncodedCatchHandler {
+ /**
+ * An array of the individual exception handlers
+ */
+ public final EncodedTypeAddrPair[] handlers;
+
+ /**
+ * The address within the code (in 2-byte words) for the catch all handler, or -1 if there is no catch all
+ * handler
+ */
+ public final int catchAllHandlerAddress;
+
+ //TODO: would it be possible to get away without having these? and generate/create these values while writing?
+ private int baseOffset;
+ private int offset;
+
+ /**
+ * Constructs a new EncodedCatchHandler
with the given values
+ * @param handlers an array of the individual exception handlers
+ * @param catchAllHandlerAddress The address within the code (in 2-byte words) for the catch all handler, or -1
+ * if there is no catch all handler
+ */
+ public EncodedCatchHandler(EncodedTypeAddrPair[] handlers, int catchAllHandlerAddress) {
+ this.handlers = handlers;
+ this.catchAllHandlerAddress = catchAllHandlerAddress;
+ }
+
+ /**
+ * This is used internally to construct a new EncodedCatchHandler
while reading in a
+ * DexFile
+ * @param dexFile the DexFile
that is being read in
+ * @param in the Input object to read the EncodedCatchHandler
from
+ */
+ private EncodedCatchHandler(DexFile dexFile, Input in) {
+ int handlerCount = in.readSignedLeb128();
+
+ if (handlerCount < 0) {
+ handlers = new EncodedTypeAddrPair[-1 * handlerCount];
+ } else {
+ handlers = new EncodedTypeAddrPair[handlerCount];
+ }
+
+ for (int i=0; iEncodedCatchHandler from the beginning of the
+ * encoded_catch_handler_list structure
+ */
+ private int getOffsetInList() {
+ return offset-baseOffset;
+ }
+
+ /**
+ * Places the EncodedCatchHandler
, storing the offset and baseOffset, and returning the offset
+ * immediately following this EncodedCatchHandler
+ * @param offset the offset of this EncodedCatchHandler
in the DexFile
+ * @param baseOffset the offset of the beginning of the encoded_catch_handler_list structure in the
+ * DexFile
+ * @return the offset immediately following this EncodedCatchHandler
+ */
+ private int place(int offset, int baseOffset) {
+ this.offset = offset;
+ this.baseOffset = baseOffset;
+
+ int size = handlers.length;
+ if (catchAllHandlerAddress > -1) {
+ size *= -1;
+ offset += Leb128Utils.unsignedLeb128Size(catchAllHandlerAddress);
+ }
+ offset += Leb128Utils.signedLeb128Size(size);
+
+ for (EncodedTypeAddrPair handler: handlers) {
+ offset += handler.getSize();
+ }
+ return offset;
+ }
+
+ /**
+ * Writes the EncodedCatchHandler
to the given AnnotatedOutput
object
+ * @param out the AnnotatedOutput
object to write to
+ */
+ private void writeTo(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate("size: 0x" + Integer.toHexString(handlers.length) + " (" + handlers.length + ")");
+
+ int size = handlers.length;
+ if (catchAllHandlerAddress > -1) {
+ size = size * -1;
+ }
+ out.writeSignedLeb128(size);
+
+ int index = 0;
+ for (EncodedTypeAddrPair handler: handlers) {
+ out.annotate(0, "[" + index++ + "] encoded_type_addr_pair");
+ out.indent();
+ handler.writeTo(out);
+ out.deindent();
+ }
+
+ if (catchAllHandlerAddress > -1) {
+ out.annotate("catch_all_addr: 0x" + Integer.toHexString(catchAllHandlerAddress));
+ out.writeUnsignedLeb128(catchAllHandlerAddress);
+ }
+ } else {
+ int size = handlers.length;
+ if (catchAllHandlerAddress > -1) {
+ size = size * -1;
+ }
+ out.writeSignedLeb128(size);
+
+ for (EncodedTypeAddrPair handler: handlers) {
+ handler.writeTo(out);
+ }
+
+ if (catchAllHandlerAddress > -1) {
+ out.writeUnsignedLeb128(catchAllHandlerAddress);
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ for (EncodedTypeAddrPair handler: handlers) {
+ hash = hash * 31 + handler.hashCode();
+ }
+ hash = hash * 31 + catchAllHandlerAddress;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this==o) {
+ return true;
+ }
+ if (o==null || !this.getClass().equals(o.getClass())) {
+ return false;
+ }
+
+ EncodedCatchHandler other = (EncodedCatchHandler)o;
+ if (handlers.length != other.handlers.length || catchAllHandlerAddress != other.catchAllHandlerAddress) {
+ return false;
+ }
+
+ for (int i=0; iException that this handler handles
+ */
+ public final TypeIdItem exceptionType;
+
+ /**
+ * The address (in 2-byte words) in the code of the handler
+ */
+ public final int handlerAddress;
+
+ /**
+ * Constructs a new EncodedTypeAddrPair
with the given values
+ * @param exceptionType the type of the Exception
that this handler handles
+ * @param handlerAddress the address (in 2-byte words) in the code of the handler
+ */
+ public EncodedTypeAddrPair(TypeIdItem exceptionType, int handlerAddress) {
+ this.exceptionType = exceptionType;
+ this.handlerAddress = handlerAddress;
+ }
+
+ /**
+ * This is used internally to construct a new EncodedTypeAddrPair
while reading in a
+ * DexFile
+ * @param dexFile the DexFile
that is being read in
+ * @param in the Input object to read the EncodedCatchHandler
from
+ */
+ private EncodedTypeAddrPair(DexFile dexFile, Input in) {
+ exceptionType = dexFile.TypeIdsSection.getItemByIndex(in.readUnsignedLeb128());
+ handlerAddress = in.readUnsignedLeb128();
+ }
+
+ /**
+ * @return the size of this EncodedTypeAddrPair
+ */
+ private int getSize() {
+ return Leb128Utils.unsignedLeb128Size(exceptionType.getIndex()) +
+ Leb128Utils.unsignedLeb128Size(handlerAddress);
+ }
+
+ /**
+ * Writes the EncodedTypeAddrPair
to the given AnnotatedOutput
object
+ * @param out the AnnotatedOutput
object to write to
+ */
+ private void writeTo(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate("exception_type: " + exceptionType.getTypeDescriptor());
+ out.writeUnsignedLeb128(exceptionType.getIndex());
+
+ out.annotate("handler_addr: 0x" + Integer.toHexString(handlerAddress));
+ out.writeUnsignedLeb128(handlerAddress);
+ } else {
+ out.writeUnsignedLeb128(exceptionType.getIndex());
+ out.writeUnsignedLeb128(handlerAddress);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return exceptionType.hashCode() * 31 + handlerAddress;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this==o) {
+ return true;
+ }
+ if (o==null || !this.getClass().equals(o.getClass())) {
+ return false;
+ }
+
+ EncodedTypeAddrPair other = (EncodedTypeAddrPair)o;
+ return exceptionType == other.exceptionType && handlerAddress == other.handlerAddress;
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java b/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java
index 4e28277f..e4b55a46 100644
--- a/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/DebugInfoItem.java
@@ -1,612 +1,612 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Debug.DebugInstructionIterator;
-import org.jf.dexlib.Debug.DebugOpcode;
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.Leb128Utils;
-import org.jf.dexlib.Util.ByteArrayInput;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class DebugInfoItem extends Item {
- private int lineStart;
- private StringIdItem[] parameterNames;
- private byte[] encodedDebugInfo;
- private Item[] referencedItems;
-
- private CodeItem parent = null;
-
- /**
- * Creates a new uninitialized DebugInfoInfo
- * @param dexFile The DexFile
that this item belongs to
- */
- public DebugInfoItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new DebugInfoItem
with the given values
- * @param dexFile The DexFile
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 DebugInfoItem
with the given values
- * @param dexFile The DexFile
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 DebugInfoItem
with the given values
- */
- public static DebugInfoItem getInternedDebugInfoItem(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 stringIdSection = dexFile.StringIdsSection;
- for (int i=0; i referencedItemsList = new ArrayList- (50);
- DebugInstructionIterator.IterateInstructions(in,
- new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
- @Override
- public void ProcessStartLocal(int startOffset, 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 startOffset, 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 startOffset, 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 startOffset, int length) {
- this.length+=length;
- }
-
- @Override
- public void ProcessStartLocal(int startOffset, 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 startOffset, 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 startOffset, 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);
- }
- }
-
- /**
- * 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 startOffset, int length) {
- out.write(encodedDebugInfo, startOffset, length);
- }
-
- @Override
- public void ProcessStartLocal(int startOffset, 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 startOffset, 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 startOffset, 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 startOffset) {
- out.annotate("DBG_END_SEQUENCE");
- out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value);
- }
-
- @Override
- public void ProcessAdvancePC(int startOffset, 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 startOffset, 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 startOffset, 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 startOffset, 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 startOffset, 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 startOffset, 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 startOffset) {
- out.annotate("DBG_SET_PROLOGUE_END");
- out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value);
- }
-
- @Override
- public void ProcessSetEpilogueBegin(int startOffset) {
- out.annotate("DBG_SET_EPILOGUE_BEGIN");
- out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value);
- }
-
- @Override
- public void ProcessSetFile(int startOffset, 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 startOffset, 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
CodeItem
that this DebugInfoItem
is associated with
- * @param codeItem the CodeItem
that this DebugInfoItem
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;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Debug.DebugInstructionIterator;
+import org.jf.dexlib.Debug.DebugOpcode;
+import org.jf.dexlib.Util.AnnotatedOutput;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.Leb128Utils;
+import org.jf.dexlib.Util.ByteArrayInput;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DebugInfoItem extends Item {
+ private int lineStart;
+ private StringIdItem[] parameterNames;
+ private byte[] encodedDebugInfo;
+ private Item[] referencedItems;
+
+ private CodeItem parent = null;
+
+ /**
+ * Creates a new uninitialized DebugInfoInfo
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ public DebugInfoItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new DebugInfoItem
with the given values
+ * @param dexFile The DexFile
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 DebugInfoItem
with the given values
+ * @param dexFile The DexFile
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 DebugInfoItem
with the given values
+ */
+ public static DebugInfoItem getInternedDebugInfoItem(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 stringIdSection = dexFile.StringIdsSection;
+ for (int i=0; i referencedItemsList = new ArrayList- (50);
+ DebugInstructionIterator.IterateInstructions(in,
+ new DebugInstructionIterator.ProcessRawDebugInstructionDelegate() {
+ @Override
+ public void ProcessStartLocal(int startOffset, 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 startOffset, 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 startOffset, 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 startOffset, int length) {
+ this.length+=length;
+ }
+
+ @Override
+ public void ProcessStartLocal(int startOffset, 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 startOffset, 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 startOffset, 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);
+ }
+ }
+
+ /**
+ * 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 startOffset, int length) {
+ out.write(encodedDebugInfo, startOffset, length);
+ }
+
+ @Override
+ public void ProcessStartLocal(int startOffset, 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 startOffset, 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 startOffset, 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 startOffset) {
+ out.annotate("DBG_END_SEQUENCE");
+ out.writeByte(DebugOpcode.DBG_END_SEQUENCE.value);
+ }
+
+ @Override
+ public void ProcessAdvancePC(int startOffset, 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 startOffset, 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 startOffset, 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 startOffset, 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 startOffset, 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 startOffset, 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 startOffset) {
+ out.annotate("DBG_SET_PROLOGUE_END");
+ out.writeByte(DebugOpcode.DBG_SET_PROLOGUE_END.value);
+ }
+
+ @Override
+ public void ProcessSetEpilogueBegin(int startOffset) {
+ out.annotate("DBG_SET_EPILOGUE_BEGIN");
+ out.writeByte(DebugOpcode.DBG_SET_EPILOGUE_BEGIN.value);
+ }
+
+ @Override
+ public void ProcessSetFile(int startOffset, 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 startOffset, 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
CodeItem
that this DebugInfoItem
is associated with
+ * @param codeItem the CodeItem
that this DebugInfoItem
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;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/DexFile.java b/dexlib/src/main/java/org/jf/dexlib/DexFile.java
index 77a3a547..d3860237 100644
--- a/dexlib/src/main/java/org/jf/dexlib/DexFile.java
+++ b/dexlib/src/main/java/org/jf/dexlib/DexFile.java
@@ -1,846 +1,845 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.*;
-import org.jf.dexlib.*;
-import org.jf.dexlib.Item;
-import org.jf.dexlib.StringDataItem;
-
-import java.io.*;
-import java.security.DigestException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Collections;
-import java.util.zip.Adler32;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipException;
-import java.util.zip.ZipEntry;
-
-/**
- * Main use cases
- *
- * These are the main use cases that drove the design of this library
- *
- *
- * Annotate an existing dex file - 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)
- *
- * Canonicalize an existing dex file - 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.
- *
- * Currently, there are a couple of pieces of information that probably won't match exactly
- *
- * - the order of exception handlers in the
EncodedCatchHandlerList
for a method
- * - the ordering of some of the debug info in the
{@link org.jf.dexlib.DebugInfoItem}
for a method
- *
- *
- *
- * 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
- *
- * Creating a dex file from scratch - 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.
- *
- * 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.
- *
- *
- * Reading in the dex file - 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.
- *
- *
- * Other use cases
- *
- * 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
- *
- *
- * - deleting classes/methods/etc. from a dex file
- * - merging 2 dex files
- * - splitting a dex file
- * - moving classes from 1 dex file to another
- * - removing the debug information from a dex file
- * - obfustication of a dex file
- *
- */
-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, 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;
-
-
- /**
- * this is used to access the dex file from within inner classes, when they declare fields or
- * variable that hide fields on this object
- */
- private final DexFile dexFile = this;
-
- /**
- * Is this file an odex file? This is only set when reading in an odex file
- */
- private boolean isOdex = false;
-
-
- private int dataOffset;
- private int dataSize;
- private int fileSize;
-
- private boolean disableInterning = false;
-
-
- /**
- * 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
- * that are signed, so they will be written in the same format. See
- * getPreserveSignedRegisters()
- */
- private DexFile(boolean preserveSignedRegisters) {
- this.preserveSignedRegisters = preserveSignedRegisters;
-
- 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);
- }
-
- /**
- * 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
- * getPreserveSignedRegisters()
- * @throws IOException if an IOException occurs
- */
- public DexFile(String file, boolean preserveSignedRegisters)
- throws IOException {
- this(new File(file), preserveSignedRegisters);
- }
-
- /**
- * 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);
- }
-
- /**
- * 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 #getPreserveSignedRegisters
- * @throws IOException if an IOException occurs
- */
- public DexFile(File file, boolean preserveSignedRegisters)
- throws IOException {
- this(preserveSignedRegisters);
-
- 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 RuntimeException("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;
-
- dexMagic = org.jf.dexlib.HeaderItem.MAGIC;
- odexMagic = OdexHeaderItem.MAGIC;
-
- boolean isDex = true;
- this.isOdex = true;
- for (int i=0; i<8; i++) {
- if (magic[i] != dexMagic[i]) {
- isDex = false;
- }
- if (magic[i] != odexMagic[i]) {
- isOdex = false;
- }
- }
-
- if (isOdex) {
- byte[] odexHeaderBytes = FileUtils.readStream(inputStream, 40);
- Input odexHeaderIn = new ByteArrayInput(odexHeaderBytes);
- OdexHeaderItem odexHeader = new OdexHeaderItem(odexHeaderIn);
-
- in = new ByteArrayInput(FileUtils.readStream(inputStream, odexHeader.dexLength));
- } 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(this);
-
- 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);
-
- for (Section section: sectionsByType) {
- if (section == null) {
- 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 Section.intern()
method of ClassDefsSection
- */
- public DexFile() {
- this(true);
- }
-
- /**
- * Get the Section
containing items of the same type as the given item
- * @param item Get the Section
that contains items of this type
- * @param The specific item subclass - inferred from the passed item
- * @return the Section
containing items of the same type as the given item
- */
- public Section getSectionForItem(T item) {
- return (Section)sectionsByType[item.getItemType().SectionIndex];
- }
-
- /**
- * Get the Section
containing items of the given type
- * @param itemType the type of item
- * @return the Section
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
- * DexFile
- * @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 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;
- }
-
- /**
- * Disables adding new items to this dex file. The various getInterned*() type
- * methods on individual items will return null if there isn't an existing item
- * that matches
- */
- public void disableInterning() {
- this.disableInterning = true;
- }
-
- /**
- * @return a boolean value indicating whether interning new items has been disabled
- * for this dex file
- */
- public boolean getInterningDisabled() {
- return disableInterning;
- }
-
- /**
- * @return a boolean value indicating whether this dex file was created by reading in an odex file
- */
- public boolean isOdex() {
- return this.isOdex;
- }
-
- /**
- * 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() {
- 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 getSortAllItems()
and getInplace()
,
- * 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 AnnotatedOutput
object. If
- * out.Annotates()
is true, then annotations that document the format
- * of the dex file are written.
- *
- * You must call place()
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 calcSignature()
and
- * then calcChecksum()
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 IndexedSection
containing StringIdItem
items
- */
- public final IndexedSection StringIdsSection =
- new IndexedSection(this, ItemType.TYPE_STRING_ID_ITEM);
-
- /**
- * The IndexedSection
containing TypeIdItem
items
- */
- public final IndexedSection TypeIdsSection =
- new IndexedSection(this, ItemType.TYPE_TYPE_ID_ITEM);
-
- /**
- * The IndexedSection
containing ProtoIdItem
items
- */
- public final IndexedSection ProtoIdsSection =
- new IndexedSection(this, ItemType.TYPE_PROTO_ID_ITEM);
-
- /**
- * The IndexedSection
containing FieldIdItem
items
- */
- public final IndexedSection FieldIdsSection =
- new IndexedSection(this, ItemType.TYPE_FIELD_ID_ITEM);
-
- /**
- * The IndexedSection
containing MethodIdItem
items
- */
- public final IndexedSection MethodIdsSection =
- new IndexedSection(this, ItemType.TYPE_METHOD_ID_ITEM);
-
- /**
- * The IndexedSection
containing ClassDefItem
items
- */
- public final IndexedSection ClassDefsSection =
- new IndexedSection(this, ItemType.TYPE_CLASS_DEF_ITEM) {
-
- public int placeAt(int offset) {
- if (dexFile.getInplace()) {
- return super.placeAt(offset);
- }
-
- int ret = ClassDefItem.placeClassDefItems(this, offset);
-
- Collections.sort(this.items, new Comparator() {
-
- public int compare(ClassDefItem a, ClassDefItem b) {
- return a.getOffset() - b.getOffset();
- }
- });
-
- this.offset = items.get(0).getOffset();
- return ret;
- }
- };
-
- /**
- * The OffsettedSection
containing TypeListItem
items
- */
- public final OffsettedSection TypeListsSection =
- new OffsettedSection(this, ItemType.TYPE_TYPE_LIST);
-
- /**
- * The OffsettedSection
containing AnnotationSetRefList
items
- */
- public final OffsettedSection AnnotationSetRefListsSection =
- new OffsettedSection(this, ItemType.TYPE_ANNOTATION_SET_REF_LIST);
-
- /**
- * The OffsettedSection
containing AnnotationSetItem
items
- */
- public final OffsettedSection AnnotationSetsSection =
- new OffsettedSection(this, ItemType.TYPE_ANNOTATION_SET_ITEM);
-
- /**
- * The OffsettedSection
containing ClassDataItem
items
- */
- public final OffsettedSection ClassDataSection =
- new OffsettedSection(this, ItemType.TYPE_CLASS_DATA_ITEM);
-
- /**
- * The OffsettedSection
containing CodeItem
items
- */
- public final OffsettedSection CodeItemsSection =
- new OffsettedSection(this, ItemType.TYPE_CODE_ITEM);
-
- /**
- * The OffsettedSection
containing StringDataItem
items
- */
- public final OffsettedSection StringDataSection =
- new OffsettedSection(this, ItemType.TYPE_STRING_DATA_ITEM);
-
- /**
- * The OffsettedSection
containing DebugInfoItem
items
- */
- public final OffsettedSection DebugInfoItemsSection =
- new OffsettedSection(this, ItemType.TYPE_DEBUG_INFO_ITEM);
-
- /**
- * The OffsettedSection
containing AnnotationItem
items
- */
- public final OffsettedSection AnnotationsSection =
- new OffsettedSection(this, ItemType.TYPE_ANNOTATION_ITEM);
-
- /**
- * The OffsettedSection
containing EncodedArrayItem
items
- */
- public final OffsettedSection EncodedArraysSection =
- new OffsettedSection(this, ItemType.TYPE_ENCODED_ARRAY_ITEM);
-
- /**
- * The OffsettedSection
containing AnnotationDirectoryItem
items
- */
- public final OffsettedSection AnnotationDirectoriesSection =
- new OffsettedSection(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 .dex
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);
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.*;
+import org.jf.dexlib.*;
+import org.jf.dexlib.Item;
+import org.jf.dexlib.StringDataItem;
+
+import java.io.*;
+import java.security.DigestException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Collections;
+import java.util.zip.Adler32;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipException;
+import java.util.zip.ZipEntry;
+
+/**
+ * Main use cases
+ *
+ * These are the main use cases that drove the design of this library
+ *
+ *
+ * Annotate an existing dex file - 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)
+ *
+ * Canonicalize an existing dex file - 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.
+ *
+ * Currently, there are a couple of pieces of information that probably won't match exactly
+ *
+ * - the order of exception handlers in the
EncodedCatchHandlerList
for a method
+ * - the ordering of some of the debug info in the
{@link org.jf.dexlib.DebugInfoItem}
for a method
+ *
+ *
+ *
+ * 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
+ *
+ * Creating a dex file from scratch - 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.
+ *
+ * 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.
+ *
+ *
+ * Reading in the dex file - 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.
+ *
+ *
+ * Other use cases
+ *
+ * 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
+ *
+ *
+ * - deleting classes/methods/etc. from a dex file
+ * - merging 2 dex files
+ * - splitting a dex file
+ * - moving classes from 1 dex file to another
+ * - removing the debug information from a dex file
+ * - obfustication of a dex file
+ *
+ */
+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, 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;
+
+
+ /**
+ * this is used to access the dex file from within inner classes, when they declare fields or
+ * variable that hide fields on this object
+ */
+ private final DexFile dexFile = this;
+
+ /**
+ * Is this file an odex file? This is only set when reading in an odex file
+ */
+ private boolean isOdex = false;
+
+
+ private int dataOffset;
+ private int dataSize;
+ private int fileSize;
+
+ private boolean disableInterning = false;
+
+
+ /**
+ * 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
+ * that are signed, so they will be written in the same format. See
+ * getPreserveSignedRegisters()
+ */
+ private DexFile(boolean preserveSignedRegisters) {
+ this.preserveSignedRegisters = preserveSignedRegisters;
+
+ 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);
+ }
+
+ /**
+ * 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
+ * getPreserveSignedRegisters()
+ * @throws IOException if an IOException occurs
+ */
+ public DexFile(String file, boolean preserveSignedRegisters)
+ throws IOException {
+ this(new File(file), preserveSignedRegisters);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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 #getPreserveSignedRegisters
+ * @throws IOException if an IOException occurs
+ */
+ public DexFile(File file, boolean preserveSignedRegisters)
+ throws IOException {
+ this(preserveSignedRegisters);
+
+ 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 RuntimeException("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;
+
+ dexMagic = org.jf.dexlib.HeaderItem.MAGIC;
+ odexMagic = OdexHeaderItem.MAGIC;
+
+ boolean isDex = true;
+ this.isOdex = true;
+ for (int i=0; i<8; i++) {
+ if (magic[i] != dexMagic[i]) {
+ isDex = false;
+ }
+ if (magic[i] != odexMagic[i]) {
+ isOdex = false;
+ }
+ }
+
+ if (isOdex) {
+ byte[] odexHeaderBytes = FileUtils.readStream(inputStream, 40);
+ Input odexHeaderIn = new ByteArrayInput(odexHeaderBytes);
+ OdexHeaderItem odexHeader = new OdexHeaderItem(odexHeaderIn);
+
+ in = new ByteArrayInput(FileUtils.readStream(inputStream, odexHeader.dexLength));
+ } 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(this);
+
+ 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);
+
+ for (Section section: sectionsByType) {
+ if (section == null) {
+ 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 Section.intern()
method of ClassDefsSection
+ */
+ public DexFile() {
+ this(true);
+ }
+
+ /**
+ * Get the Section
containing items of the same type as the given item
+ * @param item Get the Section
that contains items of this type
+ * @param The specific item subclass - inferred from the passed item
+ * @return the Section
containing items of the same type as the given item
+ */
+ public Section getSectionForItem(T item) {
+ return (Section)sectionsByType[item.getItemType().SectionIndex];
+ }
+
+ /**
+ * Get the Section
containing items of the given type
+ * @param itemType the type of item
+ * @return the Section
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
+ * DexFile
+ * @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 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;
+ }
+
+ /**
+ * Disables adding new items to this dex file. The various getInterned*() type
+ * methods on individual items will return null if there isn't an existing item
+ * that matches
+ */
+ public void disableInterning() {
+ this.disableInterning = true;
+ }
+
+ /**
+ * @return a boolean value indicating whether interning new items has been disabled
+ * for this dex file
+ */
+ public boolean getInterningDisabled() {
+ return disableInterning;
+ }
+
+ /**
+ * @return a boolean value indicating whether this dex file was created by reading in an odex file
+ */
+ public boolean isOdex() {
+ return this.isOdex;
+ }
+
+ /**
+ * 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() {
+ 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 getSortAllItems()
and getInplace()
,
+ * 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 AnnotatedOutput
object. If
+ * out.Annotates()
is true, then annotations that document the format
+ * of the dex file are written.
+ *
+ * You must call place()
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 calcSignature()
and
+ * then calcChecksum()
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 IndexedSection
containing StringIdItem
items
+ */
+ public final IndexedSection StringIdsSection =
+ new IndexedSection(this, ItemType.TYPE_STRING_ID_ITEM);
+
+ /**
+ * The IndexedSection
containing TypeIdItem
items
+ */
+ public final IndexedSection TypeIdsSection =
+ new IndexedSection(this, ItemType.TYPE_TYPE_ID_ITEM);
+
+ /**
+ * The IndexedSection
containing ProtoIdItem
items
+ */
+ public final IndexedSection ProtoIdsSection =
+ new IndexedSection(this, ItemType.TYPE_PROTO_ID_ITEM);
+
+ /**
+ * The IndexedSection
containing FieldIdItem
items
+ */
+ public final IndexedSection FieldIdsSection =
+ new IndexedSection(this, ItemType.TYPE_FIELD_ID_ITEM);
+
+ /**
+ * The IndexedSection
containing MethodIdItem
items
+ */
+ public final IndexedSection MethodIdsSection =
+ new IndexedSection(this, ItemType.TYPE_METHOD_ID_ITEM);
+
+ /**
+ * The IndexedSection
containing ClassDefItem
items
+ */
+ public final IndexedSection ClassDefsSection =
+ new IndexedSection(this, ItemType.TYPE_CLASS_DEF_ITEM) {
+
+ public int placeAt(int offset) {
+ if (dexFile.getInplace()) {
+ return super.placeAt(offset);
+ }
+
+ int ret = ClassDefItem.placeClassDefItems(this, offset);
+
+ Collections.sort(this.items, new Comparator() {
+
+ public int compare(ClassDefItem a, ClassDefItem b) {
+ return a.getOffset() - b.getOffset();
+ }
+ });
+
+ this.offset = items.get(0).getOffset();
+ return ret;
+ }
+ };
+
+ /**
+ * The OffsettedSection
containing TypeListItem
items
+ */
+ public final OffsettedSection TypeListsSection =
+ new OffsettedSection(this, ItemType.TYPE_TYPE_LIST);
+
+ /**
+ * The OffsettedSection
containing AnnotationSetRefList
items
+ */
+ public final OffsettedSection AnnotationSetRefListsSection =
+ new OffsettedSection(this, ItemType.TYPE_ANNOTATION_SET_REF_LIST);
+
+ /**
+ * The OffsettedSection
containing AnnotationSetItem
items
+ */
+ public final OffsettedSection AnnotationSetsSection =
+ new OffsettedSection(this, ItemType.TYPE_ANNOTATION_SET_ITEM);
+
+ /**
+ * The OffsettedSection
containing ClassDataItem
items
+ */
+ public final OffsettedSection ClassDataSection =
+ new OffsettedSection(this, ItemType.TYPE_CLASS_DATA_ITEM);
+
+ /**
+ * The OffsettedSection
containing CodeItem
items
+ */
+ public final OffsettedSection CodeItemsSection =
+ new OffsettedSection(this, ItemType.TYPE_CODE_ITEM);
+
+ /**
+ * The OffsettedSection
containing StringDataItem
items
+ */
+ public final OffsettedSection StringDataSection =
+ new OffsettedSection(this, ItemType.TYPE_STRING_DATA_ITEM);
+
+ /**
+ * The OffsettedSection
containing DebugInfoItem
items
+ */
+ public final OffsettedSection DebugInfoItemsSection =
+ new OffsettedSection(this, ItemType.TYPE_DEBUG_INFO_ITEM);
+
+ /**
+ * The OffsettedSection
containing AnnotationItem
items
+ */
+ public final OffsettedSection AnnotationsSection =
+ new OffsettedSection(this, ItemType.TYPE_ANNOTATION_ITEM);
+
+ /**
+ * The OffsettedSection
containing EncodedArrayItem
items
+ */
+ public final OffsettedSection EncodedArraysSection =
+ new OffsettedSection(this, ItemType.TYPE_ENCODED_ARRAY_ITEM);
+
+ /**
+ * The OffsettedSection
containing AnnotationDirectoryItem
items
+ */
+ public final OffsettedSection AnnotationDirectoriesSection =
+ new OffsettedSection(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 .dex
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);
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java b/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java
index 845b2494..99ef6cc7 100644
--- a/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/EncodedArrayItem.java
@@ -1,135 +1,135 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class EncodedArrayItem extends Item {
- private int hashCode = 0;
-
- private ArrayEncodedSubValue encodedArray;
-
- /**
- * Creates a new uninitialized EncodedArrayItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected EncodedArrayItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new EncodedArrayItem
with the given values
- * @param dexFile The DexFile
that this item belongs to
- * @param encodedArray The encoded array value
- */
- private EncodedArrayItem(DexFile dexFile, ArrayEncodedSubValue encodedArray) {
- super(dexFile);
- this.encodedArray = encodedArray;
- }
-
- /**
- * Returns an EncodedArrayItem
for the given values, and that has been interned into the given
- * DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param encodedArray The encoded array value
- * @return an EncodedArrayItem
for the given values, and that has been interned into the given
- */
- public static EncodedArrayItem getInternedEncodedArrayItem(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);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class EncodedArrayItem extends Item {
+ private int hashCode = 0;
+
+ private ArrayEncodedSubValue encodedArray;
+
+ /**
+ * Creates a new uninitialized EncodedArrayItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected EncodedArrayItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new EncodedArrayItem
with the given values
+ * @param dexFile The DexFile
that this item belongs to
+ * @param encodedArray The encoded array value
+ */
+ private EncodedArrayItem(DexFile dexFile, ArrayEncodedSubValue encodedArray) {
+ super(dexFile);
+ this.encodedArray = encodedArray;
+ }
+
+ /**
+ * Returns an EncodedArrayItem
for the given values, and that has been interned into the given
+ * DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param encodedArray The encoded array value
+ * @return an EncodedArrayItem
for the given values, and that has been interned into the given
+ */
+ public static EncodedArrayItem getInternedEncodedArrayItem(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);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/EncodedValue/ValueType.java b/dexlib/src/main/java/org/jf/dexlib/EncodedValue/ValueType.java
index a0729c2f..9c02b48d 100644
--- a/dexlib/src/main/java/org/jf/dexlib/EncodedValue/ValueType.java
+++ b/dexlib/src/main/java/org/jf/dexlib/EncodedValue/ValueType.java
@@ -1,86 +1,86 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.EncodedValue;
-
-import org.jf.dexlib.Util.SparseArray;
-
-public enum ValueType {
-
- VALUE_BYTE((byte) 0x00),
- VALUE_SHORT((byte) 0x02),
- VALUE_CHAR((byte) 0x03),
- VALUE_INT((byte) 0x04),
- VALUE_LONG((byte) 0x06),
- VALUE_FLOAT((byte) 0x10),
- VALUE_DOUBLE((byte) 0x11),
- VALUE_STRING((byte) 0x17),
- VALUE_TYPE((byte) 0x18),
- VALUE_FIELD((byte) 0x19),
- VALUE_METHOD((byte) 0x1a),
- VALUE_ENUM((byte) 0x1b),
- VALUE_ARRAY((byte) 0x1c),
- VALUE_ANNOTATION((byte) 0x1d),
- VALUE_NULL((byte) 0x1e),
- VALUE_BOOLEAN((byte) 0x1f);
-
- /**
- * A map to facilitate looking up a ValueType
by byte value
- */
- private final static SparseArray valueTypeIntegerMap;
-
- static {
- /** build the valueTypeIntegerMap
object */
- valueTypeIntegerMap = new SparseArray(16);
-
- for (ValueType valueType : ValueType.values()) {
- valueTypeIntegerMap.put(valueType.value, valueType);
- }
- }
-
- /**
- * The byte value for this ValueType
- */
- public final byte value;
-
- private ValueType(byte value) {
- this.value = value;
- }
-
- /**
- * Converts a byte value to the corresponding ValueType enum value,
- * or null if the value isn't a valid ValueType value
- *
- * @param valueType the byte value to convert to a ValueType
- * @return the ValueType enum value corresponding to valueType, or null
- * if not a valid ValueType value
- */
- public static ValueType fromByte(byte valueType) {
- return valueTypeIntegerMap.get(valueType);
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.EncodedValue;
+
+import org.jf.dexlib.Util.SparseArray;
+
+public enum ValueType {
+
+ VALUE_BYTE((byte) 0x00),
+ VALUE_SHORT((byte) 0x02),
+ VALUE_CHAR((byte) 0x03),
+ VALUE_INT((byte) 0x04),
+ VALUE_LONG((byte) 0x06),
+ VALUE_FLOAT((byte) 0x10),
+ VALUE_DOUBLE((byte) 0x11),
+ VALUE_STRING((byte) 0x17),
+ VALUE_TYPE((byte) 0x18),
+ VALUE_FIELD((byte) 0x19),
+ VALUE_METHOD((byte) 0x1a),
+ VALUE_ENUM((byte) 0x1b),
+ VALUE_ARRAY((byte) 0x1c),
+ VALUE_ANNOTATION((byte) 0x1d),
+ VALUE_NULL((byte) 0x1e),
+ VALUE_BOOLEAN((byte) 0x1f);
+
+ /**
+ * A map to facilitate looking up a ValueType
by byte value
+ */
+ private final static SparseArray valueTypeIntegerMap;
+
+ static {
+ /** build the valueTypeIntegerMap
object */
+ valueTypeIntegerMap = new SparseArray(16);
+
+ for (ValueType valueType : ValueType.values()) {
+ valueTypeIntegerMap.put(valueType.value, valueType);
+ }
+ }
+
+ /**
+ * The byte value for this ValueType
+ */
+ public final byte value;
+
+ private ValueType(byte value) {
+ this.value = value;
+ }
+
+ /**
+ * Converts a byte value to the corresponding ValueType enum value,
+ * or null if the value isn't a valid ValueType value
+ *
+ * @param valueType the byte value to convert to a ValueType
+ * @return the ValueType enum value corresponding to valueType, or null
+ * if not a valid ValueType value
+ */
+ public static ValueType fromByte(byte valueType) {
+ return valueTypeIntegerMap.get(valueType);
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java b/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java
index 7160fa00..8c9245ac 100644
--- a/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java
@@ -1,217 +1,217 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class FieldIdItem extends Item {
- private int hashCode = 0;
-
- private TypeIdItem classType;
- private TypeIdItem fieldType;
- private StringIdItem fieldName;
-
- /**
- * Creates a new uninitialized FieldIdItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected FieldIdItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new FieldIdItem
for the given class, type and name
- * @param dexFile The DexFile
that this item belongs to
- * @param classType the class that the field is a member of
- * @param fieldType the type of the field
- * @param fieldName the name of the field
- */
- private FieldIdItem(DexFile dexFile, TypeIdItem classType, TypeIdItem fieldType, StringIdItem fieldName) {
- this(dexFile);
-
- assert classType.dexFile == dexFile;
- assert fieldType.dexFile == dexFile;
- assert fieldName.dexFile == dexFile;
-
- this.classType = classType;
- this.fieldType = fieldType;
- this.fieldName = fieldName;
- }
-
- /**
- * Returns a FieldIdItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param classType the class that the field is a member of
- * @param fieldType the type of the field
- * @param fieldName the name of the field
- * @return a FieldIdItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static FieldIdItem getInternedFieldIdItem(DexFile dexFile, TypeIdItem classType, TypeIdItem fieldType,
- StringIdItem fieldName) {
- FieldIdItem fieldIdItem = new FieldIdItem(dexFile, classType, fieldType, fieldName);
- return dexFile.FieldIdsSection.intern(fieldIdItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- classType = dexFile.TypeIdsSection.getItemByIndex(in.readShort());
- fieldType = dexFile.TypeIdsSection.getItemByIndex(in.readShort());
- fieldName = dexFile.StringIdsSection.getItemByIndex(in.readInt());
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return offset + 8;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(2, "class_type: " + classType.getTypeDescriptor());
- out.annotate(2, "field_type: " + fieldType.getTypeDescriptor());
- out.annotate(4, "field_name: " + fieldName.getStringValue());
- }
-
- out.writeShort(classType.getIndex());
- out.writeShort(fieldType.getIndex());
- out.writeInt(fieldName.getIndex());
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_FIELD_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- String parentClass = classType.getTypeDescriptor();
- //strip off the leading L and trailing ;
- parentClass = parentClass.substring(1, parentClass.length() - 1);
-
- return parentClass + "/" + fieldName.getStringValue() +
- ":" + fieldType.getTypeDescriptor();
- }
-
- /** {@inheritDoc} */
- public int compareTo(FieldIdItem o) {
- int result = classType.compareTo(o.classType);
- if (result != 0) {
- return result;
- }
-
- result = fieldName.compareTo(o.fieldName);
- if (result != 0) {
- return result;
- }
-
- return fieldType.compareTo(o.fieldType);
- }
-
- /**
- * @return the class that this field is a member of
- */
- public TypeIdItem getContainingClass() {
- return classType;
- }
-
- /**
- * @return the type of this field
- */
- public TypeIdItem getFieldType() {
- return fieldType;
- }
-
- /**
- * @return the field name
- */
- public StringIdItem getFieldName() {
- return fieldName;
- }
-
- String cachedFieldString = null;
- /**
- * @return a string formatted like LclassName;->fieldName:fieldType
- */
- public String getFieldString() {
- if (cachedFieldString == null) {
- String typeDescriptor = classType.getTypeDescriptor();
- String fieldName = this.fieldName.getStringValue();
- String fieldType = this.fieldType.getTypeDescriptor();
-
- StringBuffer sb = new StringBuffer(typeDescriptor.length() + fieldName.length() + fieldType.length() + 3);
- sb.append(typeDescriptor);
- sb.append("->");
- sb.append(fieldName);
- sb.append(":");
- sb.append(fieldType);
- cachedFieldString = sb.toString();
- }
- return cachedFieldString;
- }
-
- /**
- * calculate and cache the hashcode
- */
- private void calcHashCode() {
- hashCode = classType.hashCode();
- hashCode = 31 * hashCode + fieldType.hashCode();
- hashCode = 31 * hashCode + fieldName.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;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- FieldIdItem other = (FieldIdItem)o;
- return (classType == other.classType &&
- fieldType == other.fieldType &&
- fieldName == other.fieldName);
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class FieldIdItem extends Item {
+ private int hashCode = 0;
+
+ private TypeIdItem classType;
+ private TypeIdItem fieldType;
+ private StringIdItem fieldName;
+
+ /**
+ * Creates a new uninitialized FieldIdItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected FieldIdItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new FieldIdItem
for the given class, type and name
+ * @param dexFile The DexFile
that this item belongs to
+ * @param classType the class that the field is a member of
+ * @param fieldType the type of the field
+ * @param fieldName the name of the field
+ */
+ private FieldIdItem(DexFile dexFile, TypeIdItem classType, TypeIdItem fieldType, StringIdItem fieldName) {
+ this(dexFile);
+
+ assert classType.dexFile == dexFile;
+ assert fieldType.dexFile == dexFile;
+ assert fieldName.dexFile == dexFile;
+
+ this.classType = classType;
+ this.fieldType = fieldType;
+ this.fieldName = fieldName;
+ }
+
+ /**
+ * Returns a FieldIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param classType the class that the field is a member of
+ * @param fieldType the type of the field
+ * @param fieldName the name of the field
+ * @return a FieldIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static FieldIdItem getInternedFieldIdItem(DexFile dexFile, TypeIdItem classType, TypeIdItem fieldType,
+ StringIdItem fieldName) {
+ FieldIdItem fieldIdItem = new FieldIdItem(dexFile, classType, fieldType, fieldName);
+ return dexFile.FieldIdsSection.intern(fieldIdItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ classType = dexFile.TypeIdsSection.getItemByIndex(in.readShort());
+ fieldType = dexFile.TypeIdsSection.getItemByIndex(in.readShort());
+ fieldName = dexFile.StringIdsSection.getItemByIndex(in.readInt());
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return offset + 8;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(2, "class_type: " + classType.getTypeDescriptor());
+ out.annotate(2, "field_type: " + fieldType.getTypeDescriptor());
+ out.annotate(4, "field_name: " + fieldName.getStringValue());
+ }
+
+ out.writeShort(classType.getIndex());
+ out.writeShort(fieldType.getIndex());
+ out.writeInt(fieldName.getIndex());
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_FIELD_ID_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ String parentClass = classType.getTypeDescriptor();
+ //strip off the leading L and trailing ;
+ parentClass = parentClass.substring(1, parentClass.length() - 1);
+
+ return parentClass + "/" + fieldName.getStringValue() +
+ ":" + fieldType.getTypeDescriptor();
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(FieldIdItem o) {
+ int result = classType.compareTo(o.classType);
+ if (result != 0) {
+ return result;
+ }
+
+ result = fieldName.compareTo(o.fieldName);
+ if (result != 0) {
+ return result;
+ }
+
+ return fieldType.compareTo(o.fieldType);
+ }
+
+ /**
+ * @return the class that this field is a member of
+ */
+ public TypeIdItem getContainingClass() {
+ return classType;
+ }
+
+ /**
+ * @return the type of this field
+ */
+ public TypeIdItem getFieldType() {
+ return fieldType;
+ }
+
+ /**
+ * @return the field name
+ */
+ public StringIdItem getFieldName() {
+ return fieldName;
+ }
+
+ String cachedFieldString = null;
+ /**
+ * @return a string formatted like LclassName;->fieldName:fieldType
+ */
+ public String getFieldString() {
+ if (cachedFieldString == null) {
+ String typeDescriptor = classType.getTypeDescriptor();
+ String fieldName = this.fieldName.getStringValue();
+ String fieldType = this.fieldType.getTypeDescriptor();
+
+ StringBuffer sb = new StringBuffer(typeDescriptor.length() + fieldName.length() + fieldType.length() + 3);
+ sb.append(typeDescriptor);
+ sb.append("->");
+ sb.append(fieldName);
+ sb.append(":");
+ sb.append(fieldType);
+ cachedFieldString = sb.toString();
+ }
+ return cachedFieldString;
+ }
+
+ /**
+ * calculate and cache the hashcode
+ */
+ private void calcHashCode() {
+ hashCode = classType.hashCode();
+ hashCode = 31 * hashCode + fieldType.hashCode();
+ hashCode = 31 * hashCode + fieldName.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;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ FieldIdItem other = (FieldIdItem)o;
+ return (classType == other.classType &&
+ fieldType == other.fieldType &&
+ fieldName == other.fieldName);
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java b/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java
index 9d30f0ba..b7d57889 100644
--- a/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java
@@ -1,234 +1,234 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.Utf8Utils;
-
-import java.io.UnsupportedEncodingException;
-
-public class HeaderItem extends Item {
- /**
- * the file format magic number, represented as the
- * low-order bytes of a string
- */
- public static final byte[] MAGIC = new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00};//"dex\n035" + '\0';
-
-
- /** size of this section, in bytes */
- private static final int HEADER_SIZE = 0x70;
-
- /** the endianness constants */
- private static final int LITTLE_ENDIAN = 0x12345678;
- private static final int BIG_ENDIAN = 0x78562312;
-
- /**
- * Create a new uninitialized HeaderItem
- * @param dexFile The DexFile
containing this HeaderItem
- */
- protected HeaderItem(final DexFile dexFile) {
- super(dexFile);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- byte[] readMagic = in.readBytes(8);
-
- for (int i=0; i<8; i++) {
- if (MAGIC[i] != readMagic[i]) {
- throw new RuntimeException("The magic value is not the expected value");
- }
- }
-
- in.readBytes(20); //checksum
- in.readInt(); //signature
- in.readInt(); //filesize
- if (in.readInt() != HEADER_SIZE) {
- throw new RuntimeException("The header size is not the expected value (0x70)");
- }
-
- int endianTag = in.readInt();
- if (endianTag == BIG_ENDIAN) {
- throw new RuntimeException("This dex file is big endian. Only little endian is currently supported.");
- } else if (endianTag != LITTLE_ENDIAN) {
- throw new RuntimeException("The endian tag is not 0x12345678 or 0x78563412");
- }
-
- //link_size
- if (in.readInt() != 0) {
- throw new RuntimeException("This dex file has a link section, which is not supported");
- }
-
- //link_off
- if (in.readInt() != 0) {
- throw new RuntimeException("This dex file has a link section, which is not supported");
- }
-
- int sectionSize;
- int sectionOffset;
-
- //map_offset
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_MAP_LIST, 1, sectionOffset);
-
- //string_id_item
- sectionSize = in.readInt();
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_STRING_ID_ITEM, sectionSize, sectionOffset);
-
- //type_id_item
- sectionSize = in.readInt();
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_TYPE_ID_ITEM, sectionSize, sectionOffset);
-
- //proto_id_item
- sectionSize = in.readInt();
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_PROTO_ID_ITEM, sectionSize, sectionOffset);
-
- //field_id_item
- sectionSize = in.readInt();
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_FIELD_ID_ITEM, sectionSize, sectionOffset);
-
- //method_id_item
- sectionSize = in.readInt();
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_METHOD_ID_ITEM, sectionSize, sectionOffset);
-
- //class_data_item
- sectionSize = in.readInt();
- sectionOffset = in.readInt();
- readContext.addSection(ItemType.TYPE_CLASS_DEF_ITEM, sectionSize, sectionOffset);
-
- in.readInt(); //data_size
- in.readInt(); //data_off
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return HEADER_SIZE;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- StringBuilder magicBuilder = new StringBuilder();
- for (int i=0; i<8; i++) {
- magicBuilder.append((char)MAGIC[i]);
- }
-
- out.annotate("magic: " + Utf8Utils.escapeString(magicBuilder.toString()));
- out.write(MAGIC);
-
- out.annotate("checksum");
- out.writeInt(0);
-
- out.annotate("signature");
- out.write(new byte[20]);
-
- out.annotate("file_size: 0x" + Integer.toHexString(dexFile.getFileSize()) + " (" + dexFile.getFileSize() +
- " bytes)");
- out.writeInt(dexFile.getFileSize());
-
- out.annotate("header_size: 0x" + Integer.toHexString(HEADER_SIZE));
- out.writeInt(HEADER_SIZE);
-
- out.annotate("endian_tag: 0x" + Integer.toHexString(LITTLE_ENDIAN));
- out.writeInt(LITTLE_ENDIAN);
-
- out.annotate("link_size: 0");
- out.writeInt(0);
-
- out.annotate("link_off: 0");
- out.writeInt(0);
-
- out.annotate("map_off: 0x" + Integer.toHexString(dexFile.MapItem.getOffset()));
- out.writeInt(dexFile.MapItem.getOffset());
-
- out.annotate("string_ids_size: " + dexFile.StringIdsSection.getItems().size());
- out.writeInt(dexFile.StringIdsSection.getItems().size());
-
- out.annotate("string_ids_off: 0x" + Integer.toHexString(dexFile.StringIdsSection.getOffset()));
- out.writeInt(dexFile.StringIdsSection.getOffset());
-
- out.annotate("type_ids_size: " + dexFile.TypeIdsSection.getItems().size());
- out.writeInt(dexFile.TypeIdsSection.getItems().size());
-
- out.annotate("type_ids_off: 0x" + Integer.toHexString(dexFile.TypeIdsSection.getOffset()));
- out.writeInt(dexFile.TypeIdsSection.getOffset());
-
- out.annotate("proto_ids_size: " + dexFile.ProtoIdsSection.getItems().size());
- out.writeInt(dexFile.ProtoIdsSection.getItems().size());
-
- out.annotate("proto_ids_off: 0x" + Integer.toHexString(dexFile.ProtoIdsSection.getOffset()));
- out.writeInt(dexFile.ProtoIdsSection.getOffset());
-
- out.annotate("field_ids_size: " + dexFile.FieldIdsSection.getItems().size());
- out.writeInt(dexFile.FieldIdsSection.getItems().size());
-
- out.annotate("field_ids_off: 0x" + Integer.toHexString(dexFile.FieldIdsSection.getOffset()));
- out.writeInt(dexFile.FieldIdsSection.getOffset());
-
- out.annotate("method_ids_size: " + dexFile.MethodIdsSection.getItems().size());
- out.writeInt(dexFile.MethodIdsSection.getItems().size());
-
- out.annotate("method_ids_off: 0x" + Integer.toHexString(dexFile.MethodIdsSection.getOffset()));
- out.writeInt(dexFile.MethodIdsSection.getOffset());
-
- out.annotate("class_defs_size: " + dexFile.ClassDefsSection.getItems().size());
- out.writeInt(dexFile.ClassDefsSection.getItems().size());
-
- out.annotate("class_defs_off: 0x" + Integer.toHexString(dexFile.ClassDefsSection.getOffset()));
- out.writeInt(dexFile.ClassDefsSection.getOffset());
-
- out.annotate("data_size: 0x" + Integer.toHexString(dexFile.getDataSize()) + " (" + dexFile.getDataSize() +
- " bytes)");
- out.writeInt(dexFile.getDataSize());
-
- out.annotate("data_off: 0x" + Integer.toHexString(dexFile.getDataOffset()));
- out.writeInt(dexFile.getDataOffset());
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_HEADER_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "header_item";
- }
-
- /** {@inheritDoc} */
- public int compareTo(HeaderItem o) {
- //there is only 1 header item
- return 0;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.AnnotatedOutput;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.Utf8Utils;
+
+import java.io.UnsupportedEncodingException;
+
+public class HeaderItem extends Item {
+ /**
+ * the file format magic number, represented as the
+ * low-order bytes of a string
+ */
+ public static final byte[] MAGIC = new byte[] {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00};//"dex\n035" + '\0';
+
+
+ /** size of this section, in bytes */
+ private static final int HEADER_SIZE = 0x70;
+
+ /** the endianness constants */
+ private static final int LITTLE_ENDIAN = 0x12345678;
+ private static final int BIG_ENDIAN = 0x78562312;
+
+ /**
+ * Create a new uninitialized HeaderItem
+ * @param dexFile The DexFile
containing this HeaderItem
+ */
+ protected HeaderItem(final DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ byte[] readMagic = in.readBytes(8);
+
+ for (int i=0; i<8; i++) {
+ if (MAGIC[i] != readMagic[i]) {
+ throw new RuntimeException("The magic value is not the expected value");
+ }
+ }
+
+ in.readBytes(20); //checksum
+ in.readInt(); //signature
+ in.readInt(); //filesize
+ if (in.readInt() != HEADER_SIZE) {
+ throw new RuntimeException("The header size is not the expected value (0x70)");
+ }
+
+ int endianTag = in.readInt();
+ if (endianTag == BIG_ENDIAN) {
+ throw new RuntimeException("This dex file is big endian. Only little endian is currently supported.");
+ } else if (endianTag != LITTLE_ENDIAN) {
+ throw new RuntimeException("The endian tag is not 0x12345678 or 0x78563412");
+ }
+
+ //link_size
+ if (in.readInt() != 0) {
+ throw new RuntimeException("This dex file has a link section, which is not supported");
+ }
+
+ //link_off
+ if (in.readInt() != 0) {
+ throw new RuntimeException("This dex file has a link section, which is not supported");
+ }
+
+ int sectionSize;
+ int sectionOffset;
+
+ //map_offset
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_MAP_LIST, 1, sectionOffset);
+
+ //string_id_item
+ sectionSize = in.readInt();
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_STRING_ID_ITEM, sectionSize, sectionOffset);
+
+ //type_id_item
+ sectionSize = in.readInt();
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_TYPE_ID_ITEM, sectionSize, sectionOffset);
+
+ //proto_id_item
+ sectionSize = in.readInt();
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_PROTO_ID_ITEM, sectionSize, sectionOffset);
+
+ //field_id_item
+ sectionSize = in.readInt();
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_FIELD_ID_ITEM, sectionSize, sectionOffset);
+
+ //method_id_item
+ sectionSize = in.readInt();
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_METHOD_ID_ITEM, sectionSize, sectionOffset);
+
+ //class_data_item
+ sectionSize = in.readInt();
+ sectionOffset = in.readInt();
+ readContext.addSection(ItemType.TYPE_CLASS_DEF_ITEM, sectionSize, sectionOffset);
+
+ in.readInt(); //data_size
+ in.readInt(); //data_off
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return HEADER_SIZE;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ StringBuilder magicBuilder = new StringBuilder();
+ for (int i=0; i<8; i++) {
+ magicBuilder.append((char)MAGIC[i]);
+ }
+
+ out.annotate("magic: " + Utf8Utils.escapeString(magicBuilder.toString()));
+ out.write(MAGIC);
+
+ out.annotate("checksum");
+ out.writeInt(0);
+
+ out.annotate("signature");
+ out.write(new byte[20]);
+
+ out.annotate("file_size: 0x" + Integer.toHexString(dexFile.getFileSize()) + " (" + dexFile.getFileSize() +
+ " bytes)");
+ out.writeInt(dexFile.getFileSize());
+
+ out.annotate("header_size: 0x" + Integer.toHexString(HEADER_SIZE));
+ out.writeInt(HEADER_SIZE);
+
+ out.annotate("endian_tag: 0x" + Integer.toHexString(LITTLE_ENDIAN));
+ out.writeInt(LITTLE_ENDIAN);
+
+ out.annotate("link_size: 0");
+ out.writeInt(0);
+
+ out.annotate("link_off: 0");
+ out.writeInt(0);
+
+ out.annotate("map_off: 0x" + Integer.toHexString(dexFile.MapItem.getOffset()));
+ out.writeInt(dexFile.MapItem.getOffset());
+
+ out.annotate("string_ids_size: " + dexFile.StringIdsSection.getItems().size());
+ out.writeInt(dexFile.StringIdsSection.getItems().size());
+
+ out.annotate("string_ids_off: 0x" + Integer.toHexString(dexFile.StringIdsSection.getOffset()));
+ out.writeInt(dexFile.StringIdsSection.getOffset());
+
+ out.annotate("type_ids_size: " + dexFile.TypeIdsSection.getItems().size());
+ out.writeInt(dexFile.TypeIdsSection.getItems().size());
+
+ out.annotate("type_ids_off: 0x" + Integer.toHexString(dexFile.TypeIdsSection.getOffset()));
+ out.writeInt(dexFile.TypeIdsSection.getOffset());
+
+ out.annotate("proto_ids_size: " + dexFile.ProtoIdsSection.getItems().size());
+ out.writeInt(dexFile.ProtoIdsSection.getItems().size());
+
+ out.annotate("proto_ids_off: 0x" + Integer.toHexString(dexFile.ProtoIdsSection.getOffset()));
+ out.writeInt(dexFile.ProtoIdsSection.getOffset());
+
+ out.annotate("field_ids_size: " + dexFile.FieldIdsSection.getItems().size());
+ out.writeInt(dexFile.FieldIdsSection.getItems().size());
+
+ out.annotate("field_ids_off: 0x" + Integer.toHexString(dexFile.FieldIdsSection.getOffset()));
+ out.writeInt(dexFile.FieldIdsSection.getOffset());
+
+ out.annotate("method_ids_size: " + dexFile.MethodIdsSection.getItems().size());
+ out.writeInt(dexFile.MethodIdsSection.getItems().size());
+
+ out.annotate("method_ids_off: 0x" + Integer.toHexString(dexFile.MethodIdsSection.getOffset()));
+ out.writeInt(dexFile.MethodIdsSection.getOffset());
+
+ out.annotate("class_defs_size: " + dexFile.ClassDefsSection.getItems().size());
+ out.writeInt(dexFile.ClassDefsSection.getItems().size());
+
+ out.annotate("class_defs_off: 0x" + Integer.toHexString(dexFile.ClassDefsSection.getOffset()));
+ out.writeInt(dexFile.ClassDefsSection.getOffset());
+
+ out.annotate("data_size: 0x" + Integer.toHexString(dexFile.getDataSize()) + " (" + dexFile.getDataSize() +
+ " bytes)");
+ out.writeInt(dexFile.getDataSize());
+
+ out.annotate("data_off: 0x" + Integer.toHexString(dexFile.getDataOffset()));
+ out.writeInt(dexFile.getDataOffset());
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_HEADER_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "header_item";
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(HeaderItem o) {
+ //there is only 1 header item
+ return 0;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java b/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java
index 35f0d295..c11485b7 100644
--- a/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java
+++ b/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java
@@ -1,67 +1,67 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-
-public class IndexedSection extends Section {
-
- /**
- * Create a new indexed section
- * @param dexFile The DexFile
that this section belongs to
- * @param itemType The itemType that this section will hold
- */
- public IndexedSection(DexFile dexFile, ItemType itemType) {
- super(dexFile, itemType);
- }
-
- /** {@inheritDoc} */
- protected void readItems(Input in, ReadContext readContext) {
- for (int i = 0; i < items.size(); i++) {
- T item = (T)ItemFactory.makeItem(ItemType, DexFile);
- items.set(i, item);
- item.readFrom(in, i, readContext);
- }
- }
-
- /**
- * Gets the item at the specified index in this section
- * @param index the index of the item to get
- * @return the item at the specified index in this section
- * @throws IndexOutOfBoundsException if index is outside the bounds of this section
- */
- public T getItemByIndex(int index) {
- if (index == -1) {
- return null;
- }
-
- //if index is out of bounds, just let it throw an exception
- return items.get(index);
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+
+public class IndexedSection extends Section {
+
+ /**
+ * Create a new indexed section
+ * @param dexFile The DexFile
that this section belongs to
+ * @param itemType The itemType that this section will hold
+ */
+ public IndexedSection(DexFile dexFile, ItemType itemType) {
+ super(dexFile, itemType);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItems(Input in, ReadContext readContext) {
+ for (int i = 0; i < items.size(); i++) {
+ T item = (T)ItemFactory.makeItem(ItemType, DexFile);
+ items.set(i, item);
+ item.readFrom(in, i, readContext);
+ }
+ }
+
+ /**
+ * Gets the item at the specified index in this section
+ * @param index the index of the item to get
+ * @return the item at the specified index in this section
+ * @throws IndexOutOfBoundsException if index is outside the bounds of this section
+ */
+ public T getItemByIndex(int index) {
+ if (index == -1) {
+ return null;
+ }
+
+ //if index is out of bounds, just let it throw an exception
+ return items.get(index);
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/Item.java b/dexlib/src/main/java/org/jf/dexlib/Item.java
index abf312e9..21468528 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Item.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Item.java
@@ -1,182 +1,182 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AlignmentUtils;
-
-public abstract class Item implements Comparable {
- /**
- * The offset of this item in the dex file, or -1 if not known
- */
- protected int offset = -1;
-
- /**
- * The index of this item in the containing section, or -1 if not known
- */
- protected int index = -1;
-
- /**
- * The DexFile that this item is associatedr with
- */
- protected final DexFile dexFile;
-
- /**
- * The constructor that is used when reading in a DexFile
- * @param dexFile the DexFile
that this item is associated with
- */
- protected Item(DexFile dexFile) {
- this.dexFile = dexFile;
- }
-
- /**
- * Read in the item from the given input stream, and initialize the index
- * @param in the Input
object to read from
- * @param index the index within the containing section of the item being read in
- * @param readContext a ReadContext
object to hold information that is
- * only needed while reading in a file
- */
- protected void readFrom(Input in, int index, ReadContext readContext) {
- assert in.getCursor() % getItemType().ItemAlignment == 0;
-
- this.offset = in.getCursor();
- this.index = index;
- this.readItem(in, readContext);
- }
-
- /**
- * Place the item at the given offset and index, and return the offset of the byte following this item
- * @param offset The offset to place the item at
- * @param index The index of the item within the containing section
- * @return The offset of the byte following this item
- */
- protected int placeAt(int offset, int index) {
- assert offset % getItemType().ItemAlignment == 0;
- assert !dexFile.getInplace() || (offset == this.offset && this.index == index);
-
- this.offset = offset;
- this.index = index;
- return this.placeItem(offset);
- }
-
- /**
- * Write and annotate this item to the output stream
- * @param out The output stream to write and annotate to
- */
- protected void writeTo(AnnotatedOutput out) {
- assert out.getCursor() % getItemType().ItemAlignment == 0;
- assert out.getCursor() == offset;
-
- if (out.annotates()) {
- out.annotate(0, "[" + index + "] " + this.getItemType().TypeName);
- }
-
- out.indent();
- writeItem(out);
- out.deindent();
- }
-
- /**
- * Returns a human readable form of this item
- * @return a human readable form of this item
- */
- public String toString() {
- return getConciseIdentity();
- }
-
- /**
- * The method in the concrete item subclass that actually reads in the data for the item
- *
- * The logic in this method can assume that the given Input object is valid and is
- * aligned as neccessary.
- *
- * This method is for internal use only
- * @param in the Input
object to read from
- * @param readContext a ReadContext
object to hold information that is
- * only needed while reading in a file
- */
- protected abstract void readItem(Input in, ReadContext readContext);
-
- /**
- * The method should finalize the layout of the item and return the offset of the byte
- * immediately following the item.
- *
- * The implementation of this method can assume that the offset argument has already been
- * aligned based on the item's alignment requirements
- *
- * This method is for internal use only
- * @param offset the (pre-aligned) offset to place the item at
- * @return the size of the item, in bytes
- */
- protected abstract int placeItem(int offset);
-
- /**
- * The method in the concrete item subclass that actually writes and annotates the data
- * for the item.
- *
- * The logic in this method can assume that the given Output object is valid and is
- * aligned as neccessary
- *
- * @param out The AnnotatedOutput
object to write/annotate to
- */
- protected abstract void writeItem(AnnotatedOutput out);
-
- /**
- * @return An ItemType enum that represents the item type of this item
- */
- public abstract ItemType getItemType();
-
- /**
- * @return A concise (human-readable) string value that conveys the identity of this item
- */
- public abstract String getConciseIdentity();
-
-
- /**
- * @return the offset in the dex file where this item is located
- */
- public int getOffset() {
- return offset;
- }
-
- /**
- * @return the index of this item within the item's containing section
- */
- public int getIndex() {
- return index;
- }
-
- /**
- * @return the DexFile
that contains this item
- */
- public DexFile getDexFile() {
- return dexFile;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.AnnotatedOutput;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AlignmentUtils;
+
+public abstract class Item implements Comparable {
+ /**
+ * The offset of this item in the dex file, or -1 if not known
+ */
+ protected int offset = -1;
+
+ /**
+ * The index of this item in the containing section, or -1 if not known
+ */
+ protected int index = -1;
+
+ /**
+ * The DexFile that this item is associatedr with
+ */
+ protected final DexFile dexFile;
+
+ /**
+ * The constructor that is used when reading in a DexFile
+ * @param dexFile the DexFile
that this item is associated with
+ */
+ protected Item(DexFile dexFile) {
+ this.dexFile = dexFile;
+ }
+
+ /**
+ * Read in the item from the given input stream, and initialize the index
+ * @param in the Input
object to read from
+ * @param index the index within the containing section of the item being read in
+ * @param readContext a ReadContext
object to hold information that is
+ * only needed while reading in a file
+ */
+ protected void readFrom(Input in, int index, ReadContext readContext) {
+ assert in.getCursor() % getItemType().ItemAlignment == 0;
+
+ this.offset = in.getCursor();
+ this.index = index;
+ this.readItem(in, readContext);
+ }
+
+ /**
+ * Place the item at the given offset and index, and return the offset of the byte following this item
+ * @param offset The offset to place the item at
+ * @param index The index of the item within the containing section
+ * @return The offset of the byte following this item
+ */
+ protected int placeAt(int offset, int index) {
+ assert offset % getItemType().ItemAlignment == 0;
+ assert !dexFile.getInplace() || (offset == this.offset && this.index == index);
+
+ this.offset = offset;
+ this.index = index;
+ return this.placeItem(offset);
+ }
+
+ /**
+ * Write and annotate this item to the output stream
+ * @param out The output stream to write and annotate to
+ */
+ protected void writeTo(AnnotatedOutput out) {
+ assert out.getCursor() % getItemType().ItemAlignment == 0;
+ assert out.getCursor() == offset;
+
+ if (out.annotates()) {
+ out.annotate(0, "[" + index + "] " + this.getItemType().TypeName);
+ }
+
+ out.indent();
+ writeItem(out);
+ out.deindent();
+ }
+
+ /**
+ * Returns a human readable form of this item
+ * @return a human readable form of this item
+ */
+ public String toString() {
+ return getConciseIdentity();
+ }
+
+ /**
+ * The method in the concrete item subclass that actually reads in the data for the item
+ *
+ * The logic in this method can assume that the given Input object is valid and is
+ * aligned as neccessary.
+ *
+ * This method is for internal use only
+ * @param in the Input
object to read from
+ * @param readContext a ReadContext
object to hold information that is
+ * only needed while reading in a file
+ */
+ protected abstract void readItem(Input in, ReadContext readContext);
+
+ /**
+ * The method should finalize the layout of the item and return the offset of the byte
+ * immediately following the item.
+ *
+ * The implementation of this method can assume that the offset argument has already been
+ * aligned based on the item's alignment requirements
+ *
+ * This method is for internal use only
+ * @param offset the (pre-aligned) offset to place the item at
+ * @return the size of the item, in bytes
+ */
+ protected abstract int placeItem(int offset);
+
+ /**
+ * The method in the concrete item subclass that actually writes and annotates the data
+ * for the item.
+ *
+ * The logic in this method can assume that the given Output object is valid and is
+ * aligned as neccessary
+ *
+ * @param out The AnnotatedOutput
object to write/annotate to
+ */
+ protected abstract void writeItem(AnnotatedOutput out);
+
+ /**
+ * @return An ItemType enum that represents the item type of this item
+ */
+ public abstract ItemType getItemType();
+
+ /**
+ * @return A concise (human-readable) string value that conveys the identity of this item
+ */
+ public abstract String getConciseIdentity();
+
+
+ /**
+ * @return the offset in the dex file where this item is located
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * @return the index of this item within the item's containing section
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * @return the DexFile
that contains this item
+ */
+ public DexFile getDexFile() {
+ return dexFile;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/MapItem.java b/dexlib/src/main/java/org/jf/dexlib/MapItem.java
index 47c1f0dc..1fa1c8ba 100644
--- a/dexlib/src/main/java/org/jf/dexlib/MapItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/MapItem.java
@@ -1,138 +1,138 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-/**
- * This item represents a map_list item from the dex specification. It contains a
- * SectionInfo instance for every section in the DexFile, with the number of items
- * in and offset of that section.
- */
-public class MapItem extends Item {
- /**
- * This item is read in immediately after the HeaderItem, and the section info contained
- * by this item is added to the ReadContext object, which is used when reading in the other
- * sections in the dex file.
- *
- * This item should be placed last. It depends on the fact that the other sections
- * in the file have been placed.
- */
-
- /**
- * Create a new uninitialized MapItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected MapItem(final DexFile dexFile) {
- super(dexFile);
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- Section[] sections = dexFile.getOrderedSections();
- //the list returned by getOrderedSections doesn't contain the header
- //or map section, so add 2 to the length
- return offset + 4 + (sections.length + 2) * 12;
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- int size = in.readInt();
-
- for (int i=0; i 0;
- Section[] sections = dexFile.getOrderedSections();
-
- out.annotate("map_size: 0x" + Integer.toHexString(sections.length + 2) + " (" +
- Integer.toString(sections.length + 2) + ")");
- out.writeInt(sections.length + 2);
-
- int index = 0;
- out.annotate(0, "[" + index++ + "]");
- out.indent();
- writeSectionInfo(out, ItemType.TYPE_HEADER_ITEM, 1, 0);
- out.deindent();
-
- for (Section section: dexFile.getOrderedSections()) {
- out.annotate(0, "[" + index++ + "]");
- out.indent();
- writeSectionInfo(out, section.ItemType, section.getItems().size(), section.getOffset());
- out.deindent();
- }
-
- out.annotate(0, "[" + index++ + "]");
- out.indent();
- writeSectionInfo(out, ItemType.TYPE_MAP_LIST, 1, dexFile.MapItem.getOffset());
- out.deindent();
- }
-
- private void writeSectionInfo(AnnotatedOutput out, ItemType itemType, int sectionSize, int sectionOffset) {
- if (out.annotates()) {
- out.annotate(2, "item_type: " + itemType);
- out.annotate(2, "unused");
- out.annotate(4, "section_size: 0x" + Integer.toHexString(sectionSize) + " (" + sectionSize + ")");
- out.annotate(4, "section_off: 0x" + Integer.toHexString(sectionOffset));
- }
-
- out.writeShort(itemType.MapValue);
- out.writeShort(0);
- out.writeInt(sectionSize);
- out.writeInt(sectionOffset);
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_MAP_LIST;
- }
-
- /** {@inheritDoc} */
- public int compareTo(MapItem o) {
- return 0;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "map_item";
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+/**
+ * This item represents a map_list item from the dex specification. It contains a
+ * SectionInfo instance for every section in the DexFile, with the number of items
+ * in and offset of that section.
+ */
+public class MapItem extends Item {
+ /**
+ * This item is read in immediately after the HeaderItem, and the section info contained
+ * by this item is added to the ReadContext object, which is used when reading in the other
+ * sections in the dex file.
+ *
+ * This item should be placed last. It depends on the fact that the other sections
+ * in the file have been placed.
+ */
+
+ /**
+ * Create a new uninitialized MapItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected MapItem(final DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ Section[] sections = dexFile.getOrderedSections();
+ //the list returned by getOrderedSections doesn't contain the header
+ //or map section, so add 2 to the length
+ return offset + 4 + (sections.length + 2) * 12;
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ int size = in.readInt();
+
+ for (int i=0; i 0;
+ Section[] sections = dexFile.getOrderedSections();
+
+ out.annotate("map_size: 0x" + Integer.toHexString(sections.length + 2) + " (" +
+ Integer.toString(sections.length + 2) + ")");
+ out.writeInt(sections.length + 2);
+
+ int index = 0;
+ out.annotate(0, "[" + index++ + "]");
+ out.indent();
+ writeSectionInfo(out, ItemType.TYPE_HEADER_ITEM, 1, 0);
+ out.deindent();
+
+ for (Section section: dexFile.getOrderedSections()) {
+ out.annotate(0, "[" + index++ + "]");
+ out.indent();
+ writeSectionInfo(out, section.ItemType, section.getItems().size(), section.getOffset());
+ out.deindent();
+ }
+
+ out.annotate(0, "[" + index++ + "]");
+ out.indent();
+ writeSectionInfo(out, ItemType.TYPE_MAP_LIST, 1, dexFile.MapItem.getOffset());
+ out.deindent();
+ }
+
+ private void writeSectionInfo(AnnotatedOutput out, ItemType itemType, int sectionSize, int sectionOffset) {
+ if (out.annotates()) {
+ out.annotate(2, "item_type: " + itemType);
+ out.annotate(2, "unused");
+ out.annotate(4, "section_size: 0x" + Integer.toHexString(sectionSize) + " (" + sectionSize + ")");
+ out.annotate(4, "section_off: 0x" + Integer.toHexString(sectionOffset));
+ }
+
+ out.writeShort(itemType.MapValue);
+ out.writeShort(0);
+ out.writeInt(sectionSize);
+ out.writeInt(sectionOffset);
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_MAP_LIST;
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(MapItem o) {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "map_item";
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java b/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java
index 8e934b5f..61882f0f 100644
--- a/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/MethodIdItem.java
@@ -1,207 +1,207 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class MethodIdItem extends Item {
- private int hashCode = 0;
-
- private TypeIdItem classType;
- private ProtoIdItem methodPrototype;
- private StringIdItem methodName;
-
- /**
- * Creates a new uninitialized MethodIdItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected MethodIdItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new MethodIdItem
for the given class, type and name
- * @param dexFile The DexFile
that this item belongs to
- * @param classType the class that the method is a member of
- * @param methodPrototype the type of the method
- * @param methodName the name of the method
- */
- private MethodIdItem(DexFile dexFile, TypeIdItem classType, ProtoIdItem methodPrototype, StringIdItem methodName) {
- this(dexFile);
- this.classType = classType;
- this.methodPrototype = methodPrototype;
- this.methodName = methodName;
- }
-
- /**
- * Returns a MethodIdItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param classType the class that the method is a member of
- * @param methodPrototype the type of the method
- * @param methodName the name of the method
- * @return a MethodIdItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static MethodIdItem getInternedMethodIdItem(DexFile dexFile, TypeIdItem classType,
- ProtoIdItem methodPrototype, StringIdItem methodName) {
- MethodIdItem methodIdItem = new MethodIdItem(dexFile, classType, methodPrototype, methodName);
- return dexFile.MethodIdsSection.intern(methodIdItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- classType = dexFile.TypeIdsSection.getItemByIndex(in.readShort());
- methodPrototype = dexFile.ProtoIdsSection.getItemByIndex(in.readShort());
- methodName = dexFile.StringIdsSection.getItemByIndex(in.readInt());
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return offset + 8;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(2, "class_type: " + classType.getTypeDescriptor());
- out.annotate(2, "method_prototype: " + methodPrototype.getPrototypeString());
- out.annotate(4, "method_name: " + methodName.getStringValue());
- }
-
- out.writeShort(classType.getIndex());
- out.writeShort(methodPrototype.getIndex());
- out.writeInt(methodName.getIndex());
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_METHOD_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "method_id_item: " + getMethodString();
- }
-
- /** {@inheritDoc} */
- public int compareTo(MethodIdItem o) {
- int result = classType.compareTo(o.classType);
- if (result != 0) {
- return result;
- }
-
- result = methodName.compareTo(o.methodName);
- if (result != 0) {
- return result;
- }
-
- return methodPrototype.compareTo(o.methodPrototype);
- }
-
- private String cachedMethodString = null;
- /**
- * @return a string formatted like LclassName;->methodName(TTTT..)R
- */
- public String getMethodString() {
- if (cachedMethodString == null) {
- String classType = this.classType.getTypeDescriptor();
- String methodName = this.methodName.getStringValue();
- String prototypeString = methodPrototype.getPrototypeString();
-
- StringBuilder sb = new StringBuilder(classType.length() + methodName.length() + prototypeString.length() +
- 2);
- sb.append(classType);
- sb.append("->");
- sb.append(methodName);
- sb.append(prototypeString);
- cachedMethodString = sb.toString();
- }
- return cachedMethodString;
- }
-
- /**
- * @return the method prototype
- */
- public ProtoIdItem getPrototype() {
- return methodPrototype;
- }
-
- /**
- * @return the name of the method
- */
- public StringIdItem getMethodName() {
- return methodName;
- }
-
- /**
- * @return the class this method is a member of
- */
- public TypeIdItem getContainingClass() {
- return classType;
- }
-
- /**
- * calculate and cache the hashcode
- */
- private void calcHashCode() {
- hashCode = classType.hashCode();
- hashCode = 31 * hashCode + methodPrototype.hashCode();
- hashCode = 31 * hashCode + methodName.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;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- MethodIdItem other = (MethodIdItem)o;
- return (classType == other.classType &&
- methodPrototype == other.methodPrototype &&
- methodName == other.methodName);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class MethodIdItem extends Item {
+ private int hashCode = 0;
+
+ private TypeIdItem classType;
+ private ProtoIdItem methodPrototype;
+ private StringIdItem methodName;
+
+ /**
+ * Creates a new uninitialized MethodIdItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected MethodIdItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new MethodIdItem
for the given class, type and name
+ * @param dexFile The DexFile
that this item belongs to
+ * @param classType the class that the method is a member of
+ * @param methodPrototype the type of the method
+ * @param methodName the name of the method
+ */
+ private MethodIdItem(DexFile dexFile, TypeIdItem classType, ProtoIdItem methodPrototype, StringIdItem methodName) {
+ this(dexFile);
+ this.classType = classType;
+ this.methodPrototype = methodPrototype;
+ this.methodName = methodName;
+ }
+
+ /**
+ * Returns a MethodIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param classType the class that the method is a member of
+ * @param methodPrototype the type of the method
+ * @param methodName the name of the method
+ * @return a MethodIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static MethodIdItem getInternedMethodIdItem(DexFile dexFile, TypeIdItem classType,
+ ProtoIdItem methodPrototype, StringIdItem methodName) {
+ MethodIdItem methodIdItem = new MethodIdItem(dexFile, classType, methodPrototype, methodName);
+ return dexFile.MethodIdsSection.intern(methodIdItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ classType = dexFile.TypeIdsSection.getItemByIndex(in.readShort());
+ methodPrototype = dexFile.ProtoIdsSection.getItemByIndex(in.readShort());
+ methodName = dexFile.StringIdsSection.getItemByIndex(in.readInt());
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return offset + 8;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(2, "class_type: " + classType.getTypeDescriptor());
+ out.annotate(2, "method_prototype: " + methodPrototype.getPrototypeString());
+ out.annotate(4, "method_name: " + methodName.getStringValue());
+ }
+
+ out.writeShort(classType.getIndex());
+ out.writeShort(methodPrototype.getIndex());
+ out.writeInt(methodName.getIndex());
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_METHOD_ID_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "method_id_item: " + getMethodString();
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(MethodIdItem o) {
+ int result = classType.compareTo(o.classType);
+ if (result != 0) {
+ return result;
+ }
+
+ result = methodName.compareTo(o.methodName);
+ if (result != 0) {
+ return result;
+ }
+
+ return methodPrototype.compareTo(o.methodPrototype);
+ }
+
+ private String cachedMethodString = null;
+ /**
+ * @return a string formatted like LclassName;->methodName(TTTT..)R
+ */
+ public String getMethodString() {
+ if (cachedMethodString == null) {
+ String classType = this.classType.getTypeDescriptor();
+ String methodName = this.methodName.getStringValue();
+ String prototypeString = methodPrototype.getPrototypeString();
+
+ StringBuilder sb = new StringBuilder(classType.length() + methodName.length() + prototypeString.length() +
+ 2);
+ sb.append(classType);
+ sb.append("->");
+ sb.append(methodName);
+ sb.append(prototypeString);
+ cachedMethodString = sb.toString();
+ }
+ return cachedMethodString;
+ }
+
+ /**
+ * @return the method prototype
+ */
+ public ProtoIdItem getPrototype() {
+ return methodPrototype;
+ }
+
+ /**
+ * @return the name of the method
+ */
+ public StringIdItem getMethodName() {
+ return methodName;
+ }
+
+ /**
+ * @return the class this method is a member of
+ */
+ public TypeIdItem getContainingClass() {
+ return classType;
+ }
+
+ /**
+ * calculate and cache the hashcode
+ */
+ private void calcHashCode() {
+ hashCode = classType.hashCode();
+ hashCode = 31 * hashCode + methodPrototype.hashCode();
+ hashCode = 31 * hashCode + methodName.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;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ MethodIdItem other = (MethodIdItem)o;
+ return (classType == other.classType &&
+ methodPrototype == other.methodPrototype &&
+ methodName == other.methodName);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/OffsettedSection.java b/dexlib/src/main/java/org/jf/dexlib/OffsettedSection.java
index c34137fe..fa8f4212 100644
--- a/dexlib/src/main/java/org/jf/dexlib/OffsettedSection.java
+++ b/dexlib/src/main/java/org/jf/dexlib/OffsettedSection.java
@@ -1,83 +1,83 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.SparseArray;
-import org.jf.dexlib.Util.Hex;
-
-import junit.framework.Assert;
-
-public class OffsettedSection extends Section {
- public OffsettedSection(DexFile dexFile, ItemType itemType) {
- super(dexFile, itemType);
- }
-
- public void readItems(Input in, ReadContext readContext) {
- SparseArray precreatedItems = (SparseArray)readContext.getItemsByType(ItemType);
-
- assert precreatedItems.size() <= items.size(): "Trying to read " + items.size() + " items, but this section " +
- "already contains " + precreatedItems.size() + " items.";
-
- int precreatedIndex = 0;
- int nextPrecreatedOffset = Integer.MAX_VALUE;
-
- if (precreatedItems.size() > 0) {
- nextPrecreatedOffset = precreatedItems.keyAt(0);
- }
-
- for (int i = 0; i < items.size(); i++) {
- assert items.get(i) == null;
-
- T item = null;
- in.alignTo(ItemType.ItemAlignment);
- int currentOffset = in.getCursor();
-
- if (currentOffset == nextPrecreatedOffset) {
- item = precreatedItems.valueAt(precreatedIndex++);
- if (precreatedIndex < precreatedItems.size()) {
- nextPrecreatedOffset = precreatedItems.keyAt(precreatedIndex);
- } else {
- nextPrecreatedOffset = Integer.MAX_VALUE;
- }
- } else if (currentOffset > nextPrecreatedOffset) {
- //we passed by the next precreated item, something is wrong
- throw new RuntimeException("The pre-created item at offset 0x" + Hex.u4(nextPrecreatedOffset)
- + " was not read");
- } else {
- item = (T)ItemFactory.makeItem(ItemType, DexFile);
- }
-
- items.set(i, item);
- item.readFrom(in, i, readContext);
- }
-
- readContext.setItemsForSection(ItemType, items);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.SparseArray;
+import org.jf.dexlib.Util.Hex;
+
+import junit.framework.Assert;
+
+public class OffsettedSection extends Section {
+ public OffsettedSection(DexFile dexFile, ItemType itemType) {
+ super(dexFile, itemType);
+ }
+
+ public void readItems(Input in, ReadContext readContext) {
+ SparseArray precreatedItems = (SparseArray)readContext.getItemsByType(ItemType);
+
+ assert precreatedItems.size() <= items.size(): "Trying to read " + items.size() + " items, but this section " +
+ "already contains " + precreatedItems.size() + " items.";
+
+ int precreatedIndex = 0;
+ int nextPrecreatedOffset = Integer.MAX_VALUE;
+
+ if (precreatedItems.size() > 0) {
+ nextPrecreatedOffset = precreatedItems.keyAt(0);
+ }
+
+ for (int i = 0; i < items.size(); i++) {
+ assert items.get(i) == null;
+
+ T item = null;
+ in.alignTo(ItemType.ItemAlignment);
+ int currentOffset = in.getCursor();
+
+ if (currentOffset == nextPrecreatedOffset) {
+ item = precreatedItems.valueAt(precreatedIndex++);
+ if (precreatedIndex < precreatedItems.size()) {
+ nextPrecreatedOffset = precreatedItems.keyAt(precreatedIndex);
+ } else {
+ nextPrecreatedOffset = Integer.MAX_VALUE;
+ }
+ } else if (currentOffset > nextPrecreatedOffset) {
+ //we passed by the next precreated item, something is wrong
+ throw new RuntimeException("The pre-created item at offset 0x" + Hex.u4(nextPrecreatedOffset)
+ + " was not read");
+ } else {
+ item = (T)ItemFactory.makeItem(ItemType, DexFile);
+ }
+
+ items.set(i, item);
+ item.readFrom(in, i, readContext);
+ }
+
+ readContext.setItemsForSection(ItemType, items);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java b/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java
index eb19d8a5..b9744461 100644
--- a/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/ProtoIdItem.java
@@ -1,217 +1,217 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class ProtoIdItem extends Item {
- private int hashCode = 0;
-
- private StringIdItem shortyDescriptor;
- private TypeIdItem returnType;
- private TypeListItem parameters;
-
- /**
- * Creates a new uninitialized ProtoIdItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected ProtoIdItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new ProtoIdItem
with the given values
- * @param dexFile The DexFile
that this item belongs to
- * @param returnType the return type
- * @param parameters a TypeListItem
containing a list of the parameter types
- */
- private ProtoIdItem(DexFile dexFile, TypeIdItem returnType, TypeListItem parameters) {
- this(dexFile);
-
- String shortyString = returnType.toShorty();
- if (parameters != null) {
- shortyString += parameters.getShortyString();
- }
- this.shortyDescriptor = StringIdItem.getInternedStringIdItem(dexFile, shortyString);
- this.returnType = returnType;
- this.parameters = parameters;
- }
-
- /**
- * Returns a ProtoIdItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param returnType the return type
- * @param parameters a TypeListItem
containing a list of the parameter types
- * @return a ProtoIdItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static ProtoIdItem getInternedProtoIdItem(DexFile dexFile, TypeIdItem returnType, TypeListItem parameters) {
- ProtoIdItem protoIdItem = new ProtoIdItem(dexFile, returnType, parameters);
- return dexFile.ProtoIdsSection.intern(protoIdItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- shortyDescriptor = dexFile.StringIdsSection.getItemByIndex(in.readInt());
- returnType = dexFile.TypeIdsSection.getItemByIndex(in.readInt());
- parameters = (TypeListItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST, in.readInt());
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return offset + 12;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(4, "shorty_descriptor: " + shortyDescriptor.getStringValue());
- out.annotate(4, "return_type: " + returnType.getTypeDescriptor());
-
- if (parameters == null) {
- out.annotate(4, "parameters:");
- } else {
- out.annotate(4, "parameters: " + parameters.getTypeListString(""));
- }
- }
-
- out.writeInt(shortyDescriptor.getIndex());
- out.writeInt(returnType.getIndex());
- out.writeInt(parameters == null?0:parameters.getOffset());
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_PROTO_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- public int compareTo(ProtoIdItem o) {
- int result = returnType.compareTo(o.returnType);
- if (result != 0) {
- return result;
- }
-
- if (parameters == null) {
- if (o.parameters == null) {
- return 0;
- }
- return -1;
- } else if (o.parameters == null) {
- return 1;
- }
-
- return parameters.compareTo(o.parameters);
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "proto_id_item: " + getPrototypeString();
- }
-
- private String cachedPrototypeString = null;
- /**
- * @return a string in the format (TTTT..)R where TTTT.. are the parameter types and R is the return type
- */
- public String getPrototypeString() {
- if (cachedPrototypeString == null) {
- StringBuilder sb = new StringBuilder("(");
- if (parameters != null) {
- sb.append(parameters.getTypeListString(""));
- }
- sb.append(")");
- sb.append(returnType.getTypeDescriptor());
-
- cachedPrototypeString = sb.toString();
- }
- return cachedPrototypeString;
- }
-
- /**
- * @return the return type of the method
- */
- public TypeIdItem getReturnType() {
- return returnType;
- }
-
- /**
- * @return a TypeListItem
containing the method parameter types
- */
- public TypeListItem getParameters() {
- return parameters;
- }
-
- /**
- * @return the number of registers required for the parameters of this ProtoIdItem
- */
- public int getParameterRegisterCount() {
- if (parameters == null) {
- return 0;
- } else {
- return parameters.getRegisterCount();
- }
- }
-
- /**
- * calculate and cache the hashcode
- */
- private void calcHashCode() {
- hashCode = returnType.hashCode();
- hashCode = 31 * hashCode + (parameters==null?0:parameters.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;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- ProtoIdItem other = (ProtoIdItem)o;
- return (returnType == other.returnType &&
- parameters == other.parameters);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class ProtoIdItem extends Item {
+ private int hashCode = 0;
+
+ private StringIdItem shortyDescriptor;
+ private TypeIdItem returnType;
+ private TypeListItem parameters;
+
+ /**
+ * Creates a new uninitialized ProtoIdItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected ProtoIdItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new ProtoIdItem
with the given values
+ * @param dexFile The DexFile
that this item belongs to
+ * @param returnType the return type
+ * @param parameters a TypeListItem
containing a list of the parameter types
+ */
+ private ProtoIdItem(DexFile dexFile, TypeIdItem returnType, TypeListItem parameters) {
+ this(dexFile);
+
+ String shortyString = returnType.toShorty();
+ if (parameters != null) {
+ shortyString += parameters.getShortyString();
+ }
+ this.shortyDescriptor = StringIdItem.getInternedStringIdItem(dexFile, shortyString);
+ this.returnType = returnType;
+ this.parameters = parameters;
+ }
+
+ /**
+ * Returns a ProtoIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param returnType the return type
+ * @param parameters a TypeListItem
containing a list of the parameter types
+ * @return a ProtoIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static ProtoIdItem getInternedProtoIdItem(DexFile dexFile, TypeIdItem returnType, TypeListItem parameters) {
+ ProtoIdItem protoIdItem = new ProtoIdItem(dexFile, returnType, parameters);
+ return dexFile.ProtoIdsSection.intern(protoIdItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ shortyDescriptor = dexFile.StringIdsSection.getItemByIndex(in.readInt());
+ returnType = dexFile.TypeIdsSection.getItemByIndex(in.readInt());
+ parameters = (TypeListItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_TYPE_LIST, in.readInt());
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return offset + 12;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(4, "shorty_descriptor: " + shortyDescriptor.getStringValue());
+ out.annotate(4, "return_type: " + returnType.getTypeDescriptor());
+
+ if (parameters == null) {
+ out.annotate(4, "parameters:");
+ } else {
+ out.annotate(4, "parameters: " + parameters.getTypeListString(""));
+ }
+ }
+
+ out.writeInt(shortyDescriptor.getIndex());
+ out.writeInt(returnType.getIndex());
+ out.writeInt(parameters == null?0:parameters.getOffset());
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_PROTO_ID_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(ProtoIdItem o) {
+ int result = returnType.compareTo(o.returnType);
+ if (result != 0) {
+ return result;
+ }
+
+ if (parameters == null) {
+ if (o.parameters == null) {
+ return 0;
+ }
+ return -1;
+ } else if (o.parameters == null) {
+ return 1;
+ }
+
+ return parameters.compareTo(o.parameters);
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "proto_id_item: " + getPrototypeString();
+ }
+
+ private String cachedPrototypeString = null;
+ /**
+ * @return a string in the format (TTTT..)R where TTTT.. are the parameter types and R is the return type
+ */
+ public String getPrototypeString() {
+ if (cachedPrototypeString == null) {
+ StringBuilder sb = new StringBuilder("(");
+ if (parameters != null) {
+ sb.append(parameters.getTypeListString(""));
+ }
+ sb.append(")");
+ sb.append(returnType.getTypeDescriptor());
+
+ cachedPrototypeString = sb.toString();
+ }
+ return cachedPrototypeString;
+ }
+
+ /**
+ * @return the return type of the method
+ */
+ public TypeIdItem getReturnType() {
+ return returnType;
+ }
+
+ /**
+ * @return a TypeListItem
containing the method parameter types
+ */
+ public TypeListItem getParameters() {
+ return parameters;
+ }
+
+ /**
+ * @return the number of registers required for the parameters of this ProtoIdItem
+ */
+ public int getParameterRegisterCount() {
+ if (parameters == null) {
+ return 0;
+ } else {
+ return parameters.getRegisterCount();
+ }
+ }
+
+ /**
+ * calculate and cache the hashcode
+ */
+ private void calcHashCode() {
+ hashCode = returnType.hashCode();
+ hashCode = 31 * hashCode + (parameters==null?0:parameters.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;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ ProtoIdItem other = (ProtoIdItem)o;
+ return (returnType == other.returnType &&
+ parameters == other.parameters);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Section.java b/dexlib/src/main/java/org/jf/dexlib/Section.java
index 7d38381a..a9e1cc48 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Section.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Section.java
@@ -1,218 +1,218 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AlignmentUtils;
-
-import java.util.*;
-
-public abstract class Section {
- /**
- * A list of the items that this section contains.
- * If the section has been placed, this list should be in the order that the items
- * will written to the dex file
- */
- protected final ArrayList items;
-
- /**
- * A HashMap of the items in this section. This is used when interning items, to determine
- * if this section already has an item equivalent to the one that is being interned.
- * Both the key and the value should be the same object
- */
- protected HashMap uniqueItems = null;
-
- /**
- * The offset of this section within the DexFile
- */
- protected int offset = 0;
-
- /**
- * The type of item that this section holds
- */
- public final ItemType ItemType;
-
- /**
- * The DexFile
that this section belongs to
- */
- public final DexFile DexFile;
-
- /**
- * Create a new section
- * @param dexFile The DexFile
that this section belongs to
- * @param itemType The itemType that this section will hold
- */
- protected Section(DexFile dexFile, ItemType itemType) {
- this.DexFile = dexFile;
- items = new ArrayList();
- this.ItemType = itemType;
- }
-
- /**
- * Finalize the location of all items, and place them starting at the given offset
- * @param offset The offset where this section should be placed
- * @return the offset of the byte immediate after the last item in this section
- */
- protected int placeAt(int offset) {
- if (items.size() > 0) {
- offset = AlignmentUtils.alignOffset(offset, ItemType.ItemAlignment);
- assert !DexFile.getInplace() || offset == this.offset;
- this.offset = offset;
-
- for (int i=0; i < items.size(); i++) {
- T item = items.get(i);
- assert item != null;
- offset = AlignmentUtils.alignOffset(offset, ItemType.ItemAlignment);
- offset = item.placeAt(offset, i);
- }
- } else {
- this.offset = 0;
- }
-
- return offset;
- }
-
- /**
- * Write the items to the given AnnotatedOutput
- * @param out the AnnotatedOutput
object to write to
- */
- protected void writeTo(AnnotatedOutput out) {
- out.annotate(0, " ");
- out.annotate(0, "-----------------------------");
- out.annotate(0, this.ItemType.TypeName + " section");
- out.annotate(0, "-----------------------------");
- out.annotate(0, " ");
-
- for (Item item: items) {
- assert item!=null;
- out.alignTo(ItemType.ItemAlignment);
- item.writeTo(out);
- out.annotate(0, " ");
- }
- }
-
- /**
- * Read the specified number of items from the given Input
object
- * @param size The number of items to read
- * @param in The Input
object to read from
- * @param readContext a ReadContext
object to hold information that is
- * only needed while reading in a file
- */
- protected void readFrom(int size, Input in, ReadContext readContext) {
- //readItems() expects that the list will already be the correct size, so add null items
- //until we reach the specified size
- items.ensureCapacity(size);
- for (int i = items.size(); i < size; i++) {
- items.add(null);
- }
-
- in.alignTo(ItemType.ItemAlignment);
- offset = in.getCursor();
-
- //call the subclass's method that actually reads in the items
- readItems(in, readContext);
- }
-
- /**
- * This method in the concrete item subclass should read in all the items from the given Input
- * object, using any pre-created items as applicable (i.e. items that were created prior to reading in the
- * section, by other items requesting items from this section that they reference by index/offset)
- * @param in the Input
- * @param readContext a ReadContext
object to hold information that is
- * only needed while reading in a file
- */
- protected abstract void readItems(Input in, ReadContext readContext);
-
- /**
- * Gets the offset where the first item in this section is placed
- * @return the ofset where the first item in this section is placed
- */
- public int getOffset() {
- return offset;
- }
-
- /**
- * Gets a the items contained in this section as a read-only list
- * @return A read-only List
object containing the items in this section
- */
- public List getItems() {
- return Collections.unmodifiableList(items);
- }
-
- /**
- * This method checks if an item that is equivalent to the given item has already been added. If found,
- * it returns that item. If not found, it adds the given item to this section and returns it.
- * @param item the item to intern
- * @return An item from this section that is equivalent to the given item. It may or may not be the same
- * as the item passed to this method.
- */
- protected T intern(T item) {
- if (item == null) {
- return null;
- }
- T internedItem = getInternedItem(item);
- if (internedItem == null && !item.dexFile.getInterningDisabled()) {
- uniqueItems.put(item, item);
- items.add(item);
- return item;
- }
- return internedItem;
- }
-
- /**
- * Returns the interned item that is equivalent to the given item, or null
- * @param item the item to check
- * @return the interned item that is equivalent to the given item, or null
- */
- protected T getInternedItem(T item) {
- if (uniqueItems == null) {
- buildInternedItemMap();
- }
- return uniqueItems.get(item);
- }
-
- /**
- * Builds the interned item map from the items that are in this section
- */
- private void buildInternedItemMap() {
- uniqueItems = new HashMap();
- for (T item: items) {
- assert item != null;
- uniqueItems.put(item, item);
- }
- }
-
- /**
- * Sorts the items in the section
- */
- protected void sortSection() {
- Collections.sort(items);
- }
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.AnnotatedOutput;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AlignmentUtils;
+
+import java.util.*;
+
+public abstract class Section {
+ /**
+ * A list of the items that this section contains.
+ * If the section has been placed, this list should be in the order that the items
+ * will written to the dex file
+ */
+ protected final ArrayList items;
+
+ /**
+ * A HashMap of the items in this section. This is used when interning items, to determine
+ * if this section already has an item equivalent to the one that is being interned.
+ * Both the key and the value should be the same object
+ */
+ protected HashMap uniqueItems = null;
+
+ /**
+ * The offset of this section within the DexFile
+ */
+ protected int offset = 0;
+
+ /**
+ * The type of item that this section holds
+ */
+ public final ItemType ItemType;
+
+ /**
+ * The DexFile
that this section belongs to
+ */
+ public final DexFile DexFile;
+
+ /**
+ * Create a new section
+ * @param dexFile The DexFile
that this section belongs to
+ * @param itemType The itemType that this section will hold
+ */
+ protected Section(DexFile dexFile, ItemType itemType) {
+ this.DexFile = dexFile;
+ items = new ArrayList();
+ this.ItemType = itemType;
+ }
+
+ /**
+ * Finalize the location of all items, and place them starting at the given offset
+ * @param offset The offset where this section should be placed
+ * @return the offset of the byte immediate after the last item in this section
+ */
+ protected int placeAt(int offset) {
+ if (items.size() > 0) {
+ offset = AlignmentUtils.alignOffset(offset, ItemType.ItemAlignment);
+ assert !DexFile.getInplace() || offset == this.offset;
+ this.offset = offset;
+
+ for (int i=0; i < items.size(); i++) {
+ T item = items.get(i);
+ assert item != null;
+ offset = AlignmentUtils.alignOffset(offset, ItemType.ItemAlignment);
+ offset = item.placeAt(offset, i);
+ }
+ } else {
+ this.offset = 0;
+ }
+
+ return offset;
+ }
+
+ /**
+ * Write the items to the given AnnotatedOutput
+ * @param out the AnnotatedOutput
object to write to
+ */
+ protected void writeTo(AnnotatedOutput out) {
+ out.annotate(0, " ");
+ out.annotate(0, "-----------------------------");
+ out.annotate(0, this.ItemType.TypeName + " section");
+ out.annotate(0, "-----------------------------");
+ out.annotate(0, " ");
+
+ for (Item item: items) {
+ assert item!=null;
+ out.alignTo(ItemType.ItemAlignment);
+ item.writeTo(out);
+ out.annotate(0, " ");
+ }
+ }
+
+ /**
+ * Read the specified number of items from the given Input
object
+ * @param size The number of items to read
+ * @param in The Input
object to read from
+ * @param readContext a ReadContext
object to hold information that is
+ * only needed while reading in a file
+ */
+ protected void readFrom(int size, Input in, ReadContext readContext) {
+ //readItems() expects that the list will already be the correct size, so add null items
+ //until we reach the specified size
+ items.ensureCapacity(size);
+ for (int i = items.size(); i < size; i++) {
+ items.add(null);
+ }
+
+ in.alignTo(ItemType.ItemAlignment);
+ offset = in.getCursor();
+
+ //call the subclass's method that actually reads in the items
+ readItems(in, readContext);
+ }
+
+ /**
+ * This method in the concrete item subclass should read in all the items from the given Input
+ * object, using any pre-created items as applicable (i.e. items that were created prior to reading in the
+ * section, by other items requesting items from this section that they reference by index/offset)
+ * @param in the Input
+ * @param readContext a ReadContext
object to hold information that is
+ * only needed while reading in a file
+ */
+ protected abstract void readItems(Input in, ReadContext readContext);
+
+ /**
+ * Gets the offset where the first item in this section is placed
+ * @return the ofset where the first item in this section is placed
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * Gets a the items contained in this section as a read-only list
+ * @return A read-only List
object containing the items in this section
+ */
+ public List getItems() {
+ return Collections.unmodifiableList(items);
+ }
+
+ /**
+ * This method checks if an item that is equivalent to the given item has already been added. If found,
+ * it returns that item. If not found, it adds the given item to this section and returns it.
+ * @param item the item to intern
+ * @return An item from this section that is equivalent to the given item. It may or may not be the same
+ * as the item passed to this method.
+ */
+ protected T intern(T item) {
+ if (item == null) {
+ return null;
+ }
+ T internedItem = getInternedItem(item);
+ if (internedItem == null && !item.dexFile.getInterningDisabled()) {
+ uniqueItems.put(item, item);
+ items.add(item);
+ return item;
+ }
+ return internedItem;
+ }
+
+ /**
+ * Returns the interned item that is equivalent to the given item, or null
+ * @param item the item to check
+ * @return the interned item that is equivalent to the given item, or null
+ */
+ protected T getInternedItem(T item) {
+ if (uniqueItems == null) {
+ buildInternedItemMap();
+ }
+ return uniqueItems.get(item);
+ }
+
+ /**
+ * Builds the interned item map from the items that are in this section
+ */
+ private void buildInternedItemMap() {
+ uniqueItems = new HashMap();
+ for (T item: items) {
+ assert item != null;
+ uniqueItems.put(item, item);
+ }
+ }
+
+ /**
+ * Sorts the items in the section
+ */
+ protected void sortSection() {
+ Collections.sort(items);
+ }
}
\ No newline at end of file
diff --git a/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java b/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java
index 5d794101..ff94c5ab 100644
--- a/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java
@@ -1,153 +1,153 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.*;
-
-public class StringDataItem extends Item {
- private int hashCode = 0;
-
- private String stringValue;
-
- /**
- * Creates a new uninitialized StringDataItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected StringDataItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new StringDataItem
for the given string
- * @param dexFile The DexFile
that this item belongs to
- * @param stringValue The string value that this item represents
- */
- private StringDataItem(DexFile dexFile, String stringValue) {
- super(dexFile);
-
- this.stringValue = stringValue;
- }
-
- /**
- * Returns a StringDataItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param value The string value that this item represents
- * @return a StringDataItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static StringDataItem getInternedStringDataItem(DexFile dexFile, String value) {
- StringDataItem StringDataItem = new StringDataItem(dexFile, value);
- return dexFile.StringDataSection.intern(StringDataItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- in.readUnsignedLeb128(); //string length
- stringValue = Utf8Utils.utf8BytesToString(in.readNullTerminatedBytes());
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return offset + Leb128Utils.unsignedLeb128Size(stringValue.length()) +
- Utf8Utils.stringToUtf8Bytes(stringValue).length + 1;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- byte[] encodedValue = Utf8Utils.stringToUtf8Bytes(stringValue);
- if (out.annotates()) {
- out.annotate("string_size: 0x" + Integer.toHexString(stringValue.length()) + " (" + stringValue.length() +
- ")");
- out.writeUnsignedLeb128(stringValue.length());
-
- out.annotate(encodedValue.length + 1, "string_data: \"" + Utf8Utils.escapeString(stringValue) + "\"");
- } else {
- out.writeUnsignedLeb128(stringValue.length());
- }
- out.write(encodedValue);
- out.writeByte(0);
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_STRING_DATA_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "string_data_item: \"" + Utf8Utils.escapeString(getStringValue()) + "\"";
- }
-
- /** {@inheritDoc} */
- public int compareTo(StringDataItem o) {
- return getStringValue().compareTo(o.getStringValue());
- }
-
- /**
- * Get the string value of this item as a String
- * @return the string value of this item as a String
- */
- public String getStringValue() {
- return stringValue;
- }
-
- /**
- * calculate and cache the hashcode
- */
- private void calcHashCode() {
- hashCode = getStringValue().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;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- StringDataItem other = (StringDataItem)o;
- return getStringValue().equals(other.getStringValue());
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.*;
+
+public class StringDataItem extends Item {
+ private int hashCode = 0;
+
+ private String stringValue;
+
+ /**
+ * Creates a new uninitialized StringDataItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected StringDataItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new StringDataItem
for the given string
+ * @param dexFile The DexFile
that this item belongs to
+ * @param stringValue The string value that this item represents
+ */
+ private StringDataItem(DexFile dexFile, String stringValue) {
+ super(dexFile);
+
+ this.stringValue = stringValue;
+ }
+
+ /**
+ * Returns a StringDataItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param value The string value that this item represents
+ * @return a StringDataItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static StringDataItem getInternedStringDataItem(DexFile dexFile, String value) {
+ StringDataItem StringDataItem = new StringDataItem(dexFile, value);
+ return dexFile.StringDataSection.intern(StringDataItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ in.readUnsignedLeb128(); //string length
+ stringValue = Utf8Utils.utf8BytesToString(in.readNullTerminatedBytes());
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return offset + Leb128Utils.unsignedLeb128Size(stringValue.length()) +
+ Utf8Utils.stringToUtf8Bytes(stringValue).length + 1;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ byte[] encodedValue = Utf8Utils.stringToUtf8Bytes(stringValue);
+ if (out.annotates()) {
+ out.annotate("string_size: 0x" + Integer.toHexString(stringValue.length()) + " (" + stringValue.length() +
+ ")");
+ out.writeUnsignedLeb128(stringValue.length());
+
+ out.annotate(encodedValue.length + 1, "string_data: \"" + Utf8Utils.escapeString(stringValue) + "\"");
+ } else {
+ out.writeUnsignedLeb128(stringValue.length());
+ }
+ out.write(encodedValue);
+ out.writeByte(0);
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_STRING_DATA_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "string_data_item: \"" + Utf8Utils.escapeString(getStringValue()) + "\"";
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(StringDataItem o) {
+ return getStringValue().compareTo(o.getStringValue());
+ }
+
+ /**
+ * Get the string value of this item as a String
+ * @return the string value of this item as a String
+ */
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ /**
+ * calculate and cache the hashcode
+ */
+ private void calcHashCode() {
+ hashCode = getStringValue().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;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ StringDataItem other = (StringDataItem)o;
+ return getStringValue().equals(other.getStringValue());
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java b/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java
index 79195e95..95f3dbfa 100644
--- a/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java
@@ -1,148 +1,148 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Utf8Utils;
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class StringIdItem extends Item {
- private StringDataItem stringDataItem;
-
- /**
- * Creates a new uninitialized StringIdItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected StringIdItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new StringIdItem
for the given StringDataItem
- * @param dexFile The DexFile
that this item belongs to
- * @param stringDataItem The StringDataItem
that this StringIdItem
represents
- */
- protected StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
- super(dexFile);
- this.stringDataItem = stringDataItem;
- }
-
- /**
- * Returns a StringIdItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item will belong to
- * @param stringValue The string value that this item represents
- * @return a StringIdItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static StringIdItem getInternedStringIdItem(DexFile dexFile, String stringValue) {
- StringDataItem stringDataItem = StringDataItem.getInternedStringDataItem(dexFile, stringValue);
- if (stringDataItem == null) {
- return null;
- }
- StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
- return dexFile.StringIdsSection.intern(stringIdItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- int stringDataOffset = in.readInt();
-
- stringDataItem = (StringDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_STRING_DATA_ITEM,
- stringDataOffset);
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return offset + 4;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(4, stringDataItem.getConciseIdentity());
- }
-
- out.writeInt(stringDataItem.getOffset());
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_STRING_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "string_id_item: " + Utf8Utils.escapeString(getStringValue());
- }
-
- /** {@inheritDoc} */
- public int compareTo(StringIdItem o) {
- //sort by the string value
- return getStringValue().compareTo(o.getStringValue());
- }
-
- /**
- * Get the String
value that this StringIdItem
represents
- * @return the String
value that this StringIdItem
represents
- */
- public String getStringValue() {
- return stringDataItem.getStringValue();
- }
-
- /**
- * Get the StringDataItem
that this StringIdItem
references
- * @return the StringDataItem
that this StringIdItem
references
- */
- public StringDataItem getStringDataItem() {
- return stringDataItem;
- }
-
- @Override
- public int hashCode() {
- return stringDataItem.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this==o) {
- return true;
- }
- if (o==null || !this.getClass().equals(o.getClass())) {
- return false;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- StringIdItem other = (StringIdItem)o;
- return stringDataItem == other.stringDataItem;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Utf8Utils;
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class StringIdItem extends Item {
+ private StringDataItem stringDataItem;
+
+ /**
+ * Creates a new uninitialized StringIdItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected StringIdItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new StringIdItem
for the given StringDataItem
+ * @param dexFile The DexFile
that this item belongs to
+ * @param stringDataItem The StringDataItem
that this StringIdItem
represents
+ */
+ protected StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
+ super(dexFile);
+ this.stringDataItem = stringDataItem;
+ }
+
+ /**
+ * Returns a StringIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item will belong to
+ * @param stringValue The string value that this item represents
+ * @return a StringIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static StringIdItem getInternedStringIdItem(DexFile dexFile, String stringValue) {
+ StringDataItem stringDataItem = StringDataItem.getInternedStringDataItem(dexFile, stringValue);
+ if (stringDataItem == null) {
+ return null;
+ }
+ StringIdItem stringIdItem = new StringIdItem(dexFile, stringDataItem);
+ return dexFile.StringIdsSection.intern(stringIdItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ int stringDataOffset = in.readInt();
+
+ stringDataItem = (StringDataItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_STRING_DATA_ITEM,
+ stringDataOffset);
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return offset + 4;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(4, stringDataItem.getConciseIdentity());
+ }
+
+ out.writeInt(stringDataItem.getOffset());
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_STRING_ID_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "string_id_item: " + Utf8Utils.escapeString(getStringValue());
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(StringIdItem o) {
+ //sort by the string value
+ return getStringValue().compareTo(o.getStringValue());
+ }
+
+ /**
+ * Get the String
value that this StringIdItem
represents
+ * @return the String
value that this StringIdItem
represents
+ */
+ public String getStringValue() {
+ return stringDataItem.getStringValue();
+ }
+
+ /**
+ * Get the StringDataItem
that this StringIdItem
references
+ * @return the StringDataItem
that this StringIdItem
references
+ */
+ public StringDataItem getStringDataItem() {
+ return stringDataItem;
+ }
+
+ @Override
+ public int hashCode() {
+ return stringDataItem.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this==o) {
+ return true;
+ }
+ if (o==null || !this.getClass().equals(o.getClass())) {
+ return false;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ StringIdItem other = (StringIdItem)o;
+ return stringDataItem == other.stringDataItem;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/TypeIdItem.java b/dexlib/src/main/java/org/jf/dexlib/TypeIdItem.java
index 7e137986..800f6c15 100644
--- a/dexlib/src/main/java/org/jf/dexlib/TypeIdItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/TypeIdItem.java
@@ -1,182 +1,182 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-
-public class TypeIdItem extends Item {
- private StringIdItem typeDescriptor;
-
- /**
- * Creates a new uninitialized TypeIdItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected TypeIdItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new TypeIdItem
for the given StringIdItem
- * @param dexFile The DexFile
that this item will belong to
- * @param typeDescriptor The StringIdItem
containing the type descriptor that
- * this TypeIdItem
represents
- */
- private TypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
- super(dexFile);
- this.typeDescriptor = typeDescriptor;
- }
-
- /**
- * Returns a TypeIdItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item will belong to
- * @param typeDescriptor The StringIdItem
containing the type descriptor that
- * this TypeIdItem
represents
- * @return a TypeIdItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static TypeIdItem getInternedTypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
- TypeIdItem typeIdItem = new TypeIdItem(dexFile, typeDescriptor);
- return dexFile.TypeIdsSection.intern(typeIdItem);
- }
-
- /**
- * Returns a TypeIdItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item will belong to
- * @param typeDescriptor The string containing the type descriptor that this
- * TypeIdItem
represents
- * @return a TypeIdItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static TypeIdItem getInternedTypeIdItem(DexFile dexFile, String typeDescriptor) {
- StringIdItem stringIdItem = StringIdItem.getInternedStringIdItem(dexFile, typeDescriptor);
- if (stringIdItem == null) {
- return null;
- }
- TypeIdItem typeIdItem = new TypeIdItem(dexFile, stringIdItem);
- return dexFile.TypeIdsSection.intern(typeIdItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- int stringIdIndex = in.readInt();
- this.typeDescriptor = dexFile.StringIdsSection.getItemByIndex(stringIdIndex);
- }
-
- /** {@inheritDoc} */
- protected int placeItem(int offset) {
- return offset + 4;
- }
-
- /** {@inheritDoc} */
- protected void writeItem(AnnotatedOutput out) {
- if (out.annotates()) {
- out.annotate(4, typeDescriptor.getConciseIdentity());
- }
-
- out.writeInt(typeDescriptor.getIndex());
- }
-
- /** {@inheritDoc} */
- public ItemType getItemType() {
- return ItemType.TYPE_TYPE_ID_ITEM;
- }
-
- /** {@inheritDoc} */
- public String getConciseIdentity() {
- return "type_id_item: " + getTypeDescriptor();
- }
-
- /** {@inheritDoc} */
- public int compareTo(TypeIdItem o) {
- //sort by the index of the StringIdItem
- return typeDescriptor.compareTo(o.typeDescriptor);
- }
-
- /**
- * Returns the type descriptor as a String
for this type
- * @return the type descriptor as a String
for this type
- */
- public String getTypeDescriptor() {
- return typeDescriptor.getStringValue();
- }
-
- /**
- * Returns the "shorty" representation of this type, used to create the shorty prototype string for a method
- * @return the "shorty" representation of this type, used to create the shorty prototype string for a method
- */
- public String toShorty() {
- String type = getTypeDescriptor();
- if (type.length() > 1) {
- return "L";
- } else {
- return type;
- }
- }
-
- /**
- * Calculates the number of 2-byte registers that an instance of this type requires
- * @return The number of 2-byte registers that an instance of this type requires
- */
- public int getRegisterCount() {
- String type = this.getTypeDescriptor();
- /** Only the long and double primitive types are 2 words,
- * everything else is a single word
- */
- if (type.equals("J") || type.equals("D")) {
- return 2;
- } else {
- return 1;
- }
- }
-
- @Override
- public int hashCode() {
- return typeDescriptor.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this==o) {
- return true;
- }
- if (o==null || !this.getClass().equals(o.getClass())) {
- return false;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- TypeIdItem other = (TypeIdItem)o;
- return typeDescriptor == other.typeDescriptor;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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;
+
+import org.jf.dexlib.Util.Input;
+import org.jf.dexlib.Util.AnnotatedOutput;
+
+public class TypeIdItem extends Item {
+ private StringIdItem typeDescriptor;
+
+ /**
+ * Creates a new uninitialized TypeIdItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected TypeIdItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new TypeIdItem
for the given StringIdItem
+ * @param dexFile The DexFile
that this item will belong to
+ * @param typeDescriptor The StringIdItem
containing the type descriptor that
+ * this TypeIdItem
represents
+ */
+ private TypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
+ super(dexFile);
+ this.typeDescriptor = typeDescriptor;
+ }
+
+ /**
+ * Returns a TypeIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item will belong to
+ * @param typeDescriptor The StringIdItem
containing the type descriptor that
+ * this TypeIdItem
represents
+ * @return a TypeIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static TypeIdItem getInternedTypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
+ TypeIdItem typeIdItem = new TypeIdItem(dexFile, typeDescriptor);
+ return dexFile.TypeIdsSection.intern(typeIdItem);
+ }
+
+ /**
+ * Returns a TypeIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item will belong to
+ * @param typeDescriptor The string containing the type descriptor that this
+ * TypeIdItem
represents
+ * @return a TypeIdItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static TypeIdItem getInternedTypeIdItem(DexFile dexFile, String typeDescriptor) {
+ StringIdItem stringIdItem = StringIdItem.getInternedStringIdItem(dexFile, typeDescriptor);
+ if (stringIdItem == null) {
+ return null;
+ }
+ TypeIdItem typeIdItem = new TypeIdItem(dexFile, stringIdItem);
+ return dexFile.TypeIdsSection.intern(typeIdItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ int stringIdIndex = in.readInt();
+ this.typeDescriptor = dexFile.StringIdsSection.getItemByIndex(stringIdIndex);
+ }
+
+ /** {@inheritDoc} */
+ protected int placeItem(int offset) {
+ return offset + 4;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeItem(AnnotatedOutput out) {
+ if (out.annotates()) {
+ out.annotate(4, typeDescriptor.getConciseIdentity());
+ }
+
+ out.writeInt(typeDescriptor.getIndex());
+ }
+
+ /** {@inheritDoc} */
+ public ItemType getItemType() {
+ return ItemType.TYPE_TYPE_ID_ITEM;
+ }
+
+ /** {@inheritDoc} */
+ public String getConciseIdentity() {
+ return "type_id_item: " + getTypeDescriptor();
+ }
+
+ /** {@inheritDoc} */
+ public int compareTo(TypeIdItem o) {
+ //sort by the index of the StringIdItem
+ return typeDescriptor.compareTo(o.typeDescriptor);
+ }
+
+ /**
+ * Returns the type descriptor as a String
for this type
+ * @return the type descriptor as a String
for this type
+ */
+ public String getTypeDescriptor() {
+ return typeDescriptor.getStringValue();
+ }
+
+ /**
+ * Returns the "shorty" representation of this type, used to create the shorty prototype string for a method
+ * @return the "shorty" representation of this type, used to create the shorty prototype string for a method
+ */
+ public String toShorty() {
+ String type = getTypeDescriptor();
+ if (type.length() > 1) {
+ return "L";
+ } else {
+ return type;
+ }
+ }
+
+ /**
+ * Calculates the number of 2-byte registers that an instance of this type requires
+ * @return The number of 2-byte registers that an instance of this type requires
+ */
+ public int getRegisterCount() {
+ String type = this.getTypeDescriptor();
+ /** Only the long and double primitive types are 2 words,
+ * everything else is a single word
+ */
+ if (type.equals("J") || type.equals("D")) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return typeDescriptor.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this==o) {
+ return true;
+ }
+ if (o==null || !this.getClass().equals(o.getClass())) {
+ return false;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ TypeIdItem other = (TypeIdItem)o;
+ return typeDescriptor == other.typeDescriptor;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java b/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java
index ac7aed88..c601a081 100644
--- a/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java
+++ b/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java
@@ -1,258 +1,258 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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;
-
-import org.jf.dexlib.Util.Input;
-import org.jf.dexlib.Util.AnnotatedOutput;
-import org.jf.dexlib.Util.ReadOnlyArrayList;
-
-import java.util.List;
-
-public class TypeListItem extends Item {
- private int hashCode = 0;
-
- private TypeIdItem[] typeList;
-
- /**
- * Creates a new uninitialized TypeListItem
- * @param dexFile The DexFile
that this item belongs to
- */
- protected TypeListItem(DexFile dexFile) {
- super(dexFile);
- }
-
- /**
- * Creates a new TypeListItem
for the given string
- * @param dexFile The DexFile
that this item belongs to
- * @param typeList A list of the types that this TypeListItem
represents
- */
- private TypeListItem(DexFile dexFile, TypeIdItem[] typeList) {
- super(dexFile);
-
- this.typeList = typeList;
- }
-
- /**
- * Returns a TypeListItem
for the given values, and that has been interned into
- * the given DexFile
- * @param dexFile The DexFile
that this item belongs to
- * @param typeList A list of the types that this TypeListItem
represents
- * @return a TypeListItem
for the given values, and that has been interned into
- * the given DexFile
- */
- public static TypeListItem getInternedTypeListItem(DexFile dexFile, List typeList) {
- TypeIdItem[] typeArray = new TypeIdItem[typeList.size()];
- typeList.toArray(typeArray);
- TypeListItem typeListItem = new TypeListItem(dexFile, typeArray);
- return dexFile.TypeListsSection.intern(typeListItem);
- }
-
- /** {@inheritDoc} */
- protected void readItem(Input in, ReadContext readContext) {
- int size = in.readInt();
- typeList = new TypeIdItem[size];
- for (int i=0; i otherSize) {
- return 1;
- } else {
- return 0;
- }
- }
-
- /**
- * @return the number of registers required for this TypeListItem
- */
- public int getRegisterCount() {
- int wordCount = 0;
- for (TypeIdItem typeIdItem: typeList) {
- wordCount += typeIdItem.getRegisterCount();
- }
- return wordCount;
- }
-
- /**
- * @return a string consisting of the type descriptors in this TypeListItem
- * that are separated by the given separator
- * @param separator the separator between each type
- */
- public String getTypeListString(String separator) {
- int size = 0;
- for (TypeIdItem typeIdItem: typeList) {
- size += typeIdItem.getTypeDescriptor().length();
- size += separator.length();
- }
-
- StringBuilder sb = new StringBuilder(size);
- for (TypeIdItem typeIdItem: typeList) {
- sb.append(typeIdItem.getTypeDescriptor());
- sb.append(separator);
- }
- if (typeList.length > 0) {
- sb.delete(sb.length() - separator.length(), sb.length());
- }
- return sb.toString();
- }
-
- /**
- * @return a string consisting of the shorty form of the type descriptors in this
- * TypeListItem
that are directly concatenated together
- */
- public String getShortyString() {
- StringBuilder sb = new StringBuilder();
- for (TypeIdItem typeIdItem: typeList) {
- sb.append(typeIdItem.toShorty());
- }
- return sb.toString();
- }
-
- /**
- * @param index the index of the TypeIdItem
to get
- * @return the TypeIdItem
at the given index
- */
- public TypeIdItem getTypeIdItem(int index) {
- return typeList[index];
- }
-
- /**
- * @return the number of types in this TypeListItem
- */
- public int getTypeCount() {
- return typeList.length;
- }
-
- /**
- * @return an array of the TypeIdItems
in this TypeListItem
- */
- public List getTypes() {
- return new ReadOnlyArrayList(typeList);
- }
-
- /**
- * calculate and cache the hashcode
- */
- private void calcHashCode() {
- int hashCode = 1;
-
- for (TypeIdItem typeIdItem: typeList) {
- hashCode = 31 * hashCode + typeIdItem.hashCode();
- }
- this.hashCode = 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;
- }
-
- //This assumes that the referenced items have been interned in both objects.
- //This is a valid assumption because all outside code must use the static
- //"getInterned..." style methods to make new items, and any item created
- //internally is guaranteed to be interned
- TypeListItem other = (TypeListItem)o;
- if (typeList.length != other.typeList.length) {
- return false;
- }
-
- for (int i=0; i {
+ private int hashCode = 0;
+
+ private TypeIdItem[] typeList;
+
+ /**
+ * Creates a new uninitialized TypeListItem
+ * @param dexFile The DexFile
that this item belongs to
+ */
+ protected TypeListItem(DexFile dexFile) {
+ super(dexFile);
+ }
+
+ /**
+ * Creates a new TypeListItem
for the given string
+ * @param dexFile The DexFile
that this item belongs to
+ * @param typeList A list of the types that this TypeListItem
represents
+ */
+ private TypeListItem(DexFile dexFile, TypeIdItem[] typeList) {
+ super(dexFile);
+
+ this.typeList = typeList;
+ }
+
+ /**
+ * Returns a TypeListItem
for the given values, and that has been interned into
+ * the given DexFile
+ * @param dexFile The DexFile
that this item belongs to
+ * @param typeList A list of the types that this TypeListItem
represents
+ * @return a TypeListItem
for the given values, and that has been interned into
+ * the given DexFile
+ */
+ public static TypeListItem getInternedTypeListItem(DexFile dexFile, List typeList) {
+ TypeIdItem[] typeArray = new TypeIdItem[typeList.size()];
+ typeList.toArray(typeArray);
+ TypeListItem typeListItem = new TypeListItem(dexFile, typeArray);
+ return dexFile.TypeListsSection.intern(typeListItem);
+ }
+
+ /** {@inheritDoc} */
+ protected void readItem(Input in, ReadContext readContext) {
+ int size = in.readInt();
+ typeList = new TypeIdItem[size];
+ for (int i=0; i otherSize) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * @return the number of registers required for this TypeListItem
+ */
+ public int getRegisterCount() {
+ int wordCount = 0;
+ for (TypeIdItem typeIdItem: typeList) {
+ wordCount += typeIdItem.getRegisterCount();
+ }
+ return wordCount;
+ }
+
+ /**
+ * @return a string consisting of the type descriptors in this TypeListItem
+ * that are separated by the given separator
+ * @param separator the separator between each type
+ */
+ public String getTypeListString(String separator) {
+ int size = 0;
+ for (TypeIdItem typeIdItem: typeList) {
+ size += typeIdItem.getTypeDescriptor().length();
+ size += separator.length();
+ }
+
+ StringBuilder sb = new StringBuilder(size);
+ for (TypeIdItem typeIdItem: typeList) {
+ sb.append(typeIdItem.getTypeDescriptor());
+ sb.append(separator);
+ }
+ if (typeList.length > 0) {
+ sb.delete(sb.length() - separator.length(), sb.length());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * @return a string consisting of the shorty form of the type descriptors in this
+ * TypeListItem
that are directly concatenated together
+ */
+ public String getShortyString() {
+ StringBuilder sb = new StringBuilder();
+ for (TypeIdItem typeIdItem: typeList) {
+ sb.append(typeIdItem.toShorty());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * @param index the index of the TypeIdItem
to get
+ * @return the TypeIdItem
at the given index
+ */
+ public TypeIdItem getTypeIdItem(int index) {
+ return typeList[index];
+ }
+
+ /**
+ * @return the number of types in this TypeListItem
+ */
+ public int getTypeCount() {
+ return typeList.length;
+ }
+
+ /**
+ * @return an array of the TypeIdItems
in this TypeListItem
+ */
+ public List getTypes() {
+ return new ReadOnlyArrayList(typeList);
+ }
+
+ /**
+ * calculate and cache the hashcode
+ */
+ private void calcHashCode() {
+ int hashCode = 1;
+
+ for (TypeIdItem typeIdItem: typeList) {
+ hashCode = 31 * hashCode + typeIdItem.hashCode();
+ }
+ this.hashCode = 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;
+ }
+
+ //This assumes that the referenced items have been interned in both objects.
+ //This is a valid assumption because all outside code must use the static
+ //"getInterned..." style methods to make new items, and any item created
+ //internally is guaranteed to be interned
+ TypeListItem other = (TypeListItem)o;
+ if (typeList.length != other.typeList.length) {
+ return false;
+ }
+
+ for (int i=0; i accessFlagsByName;
-
- static {
- accessFlagsByName = new HashMap();
- for (AccessFlags accessFlag: AccessFlags.values()) {
- accessFlagsByName.put(accessFlag.accessFlagName, accessFlag);
- }
- }
-
- private AccessFlags(int value, String accessFlagName, boolean validForClass, boolean validForMethod,
- boolean validForField) {
- this.value = value;
- this.accessFlagName = accessFlagName;
- this.validForClass = validForClass;
- this.validForMethod = validForMethod;
- this.validForField = validForField;
- }
-
- public static AccessFlags[] getAccessFlagsForClass(int accessFlagValue) {
- int size = 0;
- for (AccessFlags accessFlag: AccessFlags.values()) {
- if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) {
- size++;
- }
- }
-
- AccessFlags[] accessFlags = new AccessFlags[size];
- int accessFlagsPosition = 0;
- for (AccessFlags accessFlag: AccessFlags.values()) {
- if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) {
- accessFlags[accessFlagsPosition++] = accessFlag;
- }
- }
- return accessFlags;
- }
-
- private static String formatAccessFlags(AccessFlags[] accessFlags) {
- int size = 0;
- for (AccessFlags accessFlag: accessFlags) {
- size += accessFlag.toString().length() + 1;
- }
-
- StringBuilder sb = new StringBuilder(size);
- for (AccessFlags accessFlag: accessFlags) {
- sb.append(accessFlag.toString());
- sb.append(" ");
- }
- if (accessFlags.length > 0) {
- sb.delete(sb.length() - 1, sb.length());
- }
- return sb.toString();
- }
-
- public static String formatAccessFlagsForClass(int accessFlagValue) {
- return formatAccessFlags(getAccessFlagsForClass(accessFlagValue));
- }
-
- public static AccessFlags[] getAccessFlagsForMethod(int accessFlagValue) {
- int size = 0;
- for (AccessFlags accessFlag: AccessFlags.values()) {
- if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) {
- size++;
- }
- }
-
- AccessFlags[] accessFlags = new AccessFlags[size];
- int accessFlagsPosition = 0;
- for (AccessFlags accessFlag: AccessFlags.values()) {
- if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) {
- accessFlags[accessFlagsPosition++] = accessFlag;
- }
- }
- return accessFlags;
- }
-
- public static String formatAccessFlagsForMethod(int accessFlagValue) {
- return formatAccessFlags(getAccessFlagsForMethod(accessFlagValue));
- }
-
- public static AccessFlags[] getAccessFlagsForField(int accessFlagValue) {
- int size = 0;
- for (AccessFlags accessFlag: AccessFlags.values()) {
- if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) {
- size++;
- }
- }
-
- AccessFlags[] accessFlags = new AccessFlags[size];
- int accessFlagsPosition = 0;
- for (AccessFlags accessFlag: AccessFlags.values()) {
- if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) {
- accessFlags[accessFlagsPosition++] = accessFlag;
- }
- }
- return accessFlags;
- }
-
- public static String formatAccessFlagsForField(int accessFlagValue) {
- return formatAccessFlags(getAccessFlagsForField(accessFlagValue));
- }
-
- public static AccessFlags getAccessFlag(String accessFlag) {
- return accessFlagsByName.get(accessFlag);
- }
-
- public int getValue() {
- return value;
- }
-
- public String toString() {
- return accessFlagName;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public enum AccessFlags
+{
+ PUBLIC(0x1, "public", true, true, true),
+ PRIVATE(0x2, "private", true, true, true),
+ PROTECTED(0x4, "protected", true, true, true),
+ STATIC(0x8, "static", true, true, true),
+ FINAL(0x10, "final", true, true, true),
+ SYNCHRONIZED(0x20, "synchronized", false, true, false),
+ VOLATILE(0x40, "volatile", false, false, true),
+ BRIDGE(0x40, "bridge", false, true, false),
+ TRANSIENT(0x80, "transient", false, false, true),
+ VARARGS(0x80, "varargs", false, true, false),
+ NATIVE(0x100, "native", false, true, false),
+ INTERFACE(0x200, "interface", true, false, false),
+ ABSTRACT(0x400, "abstract", true, true, false),
+ STRICTFP(0x800, "strictfp", false, true, false),
+ SYNTHETIC(0x1000, "synthetic", true, true, true),
+ ANNOTATION(0x2000, "annotation", true, false, false),
+ ENUM(0x4000, "enum", true, false, true),
+ CONSTRUCTOR(0x10000, "constructor", false, true, false),
+ DECLARED_SYNCHRONIZED(0x20000, "declared-synchronized", false, true, false);
+
+ private int value;
+ private String accessFlagName;
+ private boolean validForClass;
+ private boolean validForMethod;
+ private boolean validForField;
+
+ private static HashMap accessFlagsByName;
+
+ static {
+ accessFlagsByName = new HashMap();
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ accessFlagsByName.put(accessFlag.accessFlagName, accessFlag);
+ }
+ }
+
+ private AccessFlags(int value, String accessFlagName, boolean validForClass, boolean validForMethod,
+ boolean validForField) {
+ this.value = value;
+ this.accessFlagName = accessFlagName;
+ this.validForClass = validForClass;
+ this.validForMethod = validForMethod;
+ this.validForField = validForField;
+ }
+
+ public static AccessFlags[] getAccessFlagsForClass(int accessFlagValue) {
+ int size = 0;
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) {
+ size++;
+ }
+ }
+
+ AccessFlags[] accessFlags = new AccessFlags[size];
+ int accessFlagsPosition = 0;
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) {
+ accessFlags[accessFlagsPosition++] = accessFlag;
+ }
+ }
+ return accessFlags;
+ }
+
+ private static String formatAccessFlags(AccessFlags[] accessFlags) {
+ int size = 0;
+ for (AccessFlags accessFlag: accessFlags) {
+ size += accessFlag.toString().length() + 1;
+ }
+
+ StringBuilder sb = new StringBuilder(size);
+ for (AccessFlags accessFlag: accessFlags) {
+ sb.append(accessFlag.toString());
+ sb.append(" ");
+ }
+ if (accessFlags.length > 0) {
+ sb.delete(sb.length() - 1, sb.length());
+ }
+ return sb.toString();
+ }
+
+ public static String formatAccessFlagsForClass(int accessFlagValue) {
+ return formatAccessFlags(getAccessFlagsForClass(accessFlagValue));
+ }
+
+ public static AccessFlags[] getAccessFlagsForMethod(int accessFlagValue) {
+ int size = 0;
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) {
+ size++;
+ }
+ }
+
+ AccessFlags[] accessFlags = new AccessFlags[size];
+ int accessFlagsPosition = 0;
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) {
+ accessFlags[accessFlagsPosition++] = accessFlag;
+ }
+ }
+ return accessFlags;
+ }
+
+ public static String formatAccessFlagsForMethod(int accessFlagValue) {
+ return formatAccessFlags(getAccessFlagsForMethod(accessFlagValue));
+ }
+
+ public static AccessFlags[] getAccessFlagsForField(int accessFlagValue) {
+ int size = 0;
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) {
+ size++;
+ }
+ }
+
+ AccessFlags[] accessFlags = new AccessFlags[size];
+ int accessFlagsPosition = 0;
+ for (AccessFlags accessFlag: AccessFlags.values()) {
+ if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) {
+ accessFlags[accessFlagsPosition++] = accessFlag;
+ }
+ }
+ return accessFlags;
+ }
+
+ public static String formatAccessFlagsForField(int accessFlagValue) {
+ return formatAccessFlags(getAccessFlagsForField(accessFlagValue));
+ }
+
+ public static AccessFlags getAccessFlag(String accessFlag) {
+ return accessFlagsByName.get(accessFlag);
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public String toString() {
+ return accessFlagName;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java b/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java
index 63196198..8ebab80c 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java
@@ -1,364 +1,364 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-/**
- * Implementation of {@link Input} which reads the data from a
- * byte[]
instance.
- *
- * Note: As per the {@link Input } interface, multi-byte
- * reads all use little-endian order.
- */
-public class ByteArrayInput
- implements Input {
-
- /** non-null; the data itself */
- private byte[] data;
-
- /** >= 0; current read cursor */
- private int cursor;
-
- /**
- * Constructs an instance with the given data
- *
- * @param data non-null; data array to use for input
- */
- public ByteArrayInput(byte[] data) {
- if (data == null) {
- throw new NullPointerException("data == null");
- }
-
- this.data = data;
- this.cursor = 0;
- }
-
- /**
- * Gets the underlying byte[]
of this instance
- *
- * @return non-null; the byte[]
- */
- public byte[] getArray() {
- return data;
- }
-
- /** {@inheritDoc} */
- public int getCursor() {
- return cursor;
- }
-
- /** {@inheritDoc} */
- public void setCursor(int cursor) {
- if (cursor < 0 || cursor >= data.length)
- throw new IndexOutOfBoundsException("The provided cursor value " +
- "is not within the bounds of this instance's data array");
- this.cursor = cursor;
- }
-
- /** {@inheritDoc} */
- public void assertCursor(int expectedCursor) {
- if (cursor != expectedCursor) {
- throw new ExceptionWithContext("expected cursor " +
- expectedCursor + "; actual value: " + cursor);
- }
- }
-
- /** {@inheritDoc} */
- public byte readByte() {
- int readAt = cursor;
- int end = readAt + 1;
-
- if (end > data.length) {
- throwBounds();
- }
-
- cursor = end;
- return data[readAt];
- }
-
- /** {@inheritDoc} */
- public int readShort() {
- int readAt = cursor;
- int end = readAt + 2;
-
- if (end > data.length) {
- throwBounds();
- }
-
- cursor = end;
- return (int)((data[readAt] & 0xff) +
- ((data[readAt + 1] & 0xff) << 8));
- }
-
- /** {@inheritDoc} */
- public int readInt() {
- int readAt = cursor;
- int end = readAt + 4;
-
- if (end > data.length) {
- throwBounds();
- }
-
- cursor = end;
- return (data[readAt] & 0xff) +
- ((data[readAt + 1] & 0xff) << 8) +
- ((data[readAt + 2] & 0xff) << 16) +
- ((data[readAt + 3] & 0xff) << 24);
- }
-
- /** {@inheritDoc} */
- public long readLong() {
- int readAt = cursor;
- int end = readAt + 8;
-
- if (end > data.length) {
- throwBounds();
- }
-
- cursor = end;
-
- return (data[readAt] & 0xffL) |
- ((data[readAt + 1] & 0xffL) << 8) |
- ((data[readAt + 2] & 0xffL) << 16) |
- ((data[readAt + 3] & 0xffL) << 24) |
- ((data[readAt + 4] & 0xffL) << 32) |
- ((data[readAt + 5] & 0xffL) << 40) |
- ((data[readAt + 6] & 0xffL) << 48) |
- ((data[readAt + 7] & 0xffL) << 58);
- }
-
-
- /** {@inheritDoc} */
- public int readUnsignedOrSignedLeb128() {
- int end = cursor;
- int currentByteValue;
- int result;
-
- result = data[end++] & 0xff;
- if (result > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
- if (currentByteValue > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- result |= (currentByteValue & 0x7f) << 14;
- if (currentByteValue > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- result |= (currentByteValue & 0x7f) << 21;
- if (currentByteValue > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- if (currentByteValue > 0x0f) {
- throwInvalidLeb();
- }
- result |= currentByteValue << 28;
- }
- }
- }
- } else {
- cursor = end;
- return result;
- }
-
- cursor = end;
-
- //If the last byte is 0, then this was an unsigned value (incorrectly) written in a signed format
- //The caller wants to know if this is the case, so we'll return the negated value instead
- //If there was only a single byte that had a value of 0, then we would have returned in the above
- //"else"
- if (data[end-1] == 0) {
- return ~result;
- }
- return result;
- }
-
-
-
-
- /** {@inheritDoc} */
- public int readUnsignedLeb128() {
- int end = cursor;
- int currentByteValue;
- int result;
-
- result = data[end++] & 0xff;
- if (result > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
- if (currentByteValue > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- result |= (currentByteValue & 0x7f) << 14;
- if (currentByteValue > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- result |= (currentByteValue & 0x7f) << 21;
- if (currentByteValue > 0x7f) {
- currentByteValue = data[end++] & 0xff;
- if (currentByteValue > 0x0f) {
- throwInvalidLeb();
- }
- result |= currentByteValue << 28;
- }
- }
- }
- }
-
- cursor = end;
- return result;
- }
-
- /** {@inheritDoc} */
- public int readSignedLeb128() {
- int end = cursor;
- int currentByteValue;
- int result;
-
- result = data[end++] & 0xff;
- if (result <= 0x7f) {
- result = (result << 25) >> 25;
- } else {
- currentByteValue = data[end++] & 0xff;
- result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
- if (currentByteValue <= 0x7f) {
- result = (result << 18) >> 18;
- } else {
- currentByteValue = data[end++] & 0xff;
- result |= (currentByteValue & 0x7f) << 14;
- if (currentByteValue <= 0x7f) {
- result = (result << 11) >> 11;
- } else {
- currentByteValue = data[end++] & 0xff;
- result |= (currentByteValue & 0x7f) << 21;
- if (currentByteValue <= 0x7f) {
- result = (result << 4) >> 4;
- } else {
- currentByteValue = data[end++] & 0xff;
- if (currentByteValue > 0x0f) {
- throwInvalidLeb();
- }
- result |= currentByteValue << 28;
- }
- }
- }
- }
-
- cursor = end;
- return result;
- }
-
- /** {@inheritDoc} */
- public void read(byte[] bytes, int offset, int length) {
- int end = cursor + length;
-
- if (end > data.length) {
- throwBounds();
- }
-
- System.arraycopy(data, cursor, bytes, offset, length);
- cursor = end;
- }
-
- /** {@inheritDoc} */
- public void read(byte[] bytes) {
- int length = bytes.length;
- int end = cursor + length;
-
- if (end > data.length) {
- throwBounds();
- }
-
- System.arraycopy(data, cursor, bytes, 0, length);
- cursor = end;
- }
-
- /** {@inheritDoc} */
- public byte[] readBytes(int length) {
- int end = cursor + length;
-
- if (end > data.length) {
- throwBounds();
- }
-
- byte[] result = new byte[length];
- System.arraycopy(data, cursor, result, 0, length);
- cursor = end;
- return result;
- }
-
- /** {@inheritDoc} */
- public byte[] readNullTerminatedBytes() {
- int startPosition = cursor;
- while (data[cursor] != 0) {
- cursor++;
- if (cursor >= data.length) {
- throwBounds();
- }
- }
- int byteCount = cursor - startPosition;
- //skip the terminating null
- cursor++;
-
- byte[] result = new byte[byteCount];
- System.arraycopy(data, startPosition, result, 0, byteCount);
- return result;
- }
-
- /** {@inheritDoc} */
- public void skipBytes(int count) {
- int end = cursor + count;
-
- if (end > data.length) {
- throwBounds();
- }
-
- cursor = end;
- }
-
- /** {@inheritDoc} */
- public void alignTo(int alignment) {
- int end = AlignmentUtils.alignOffset(cursor, alignment);
-
- if (end > data.length) {
- throwBounds();
- }
-
- cursor = end;
- }
-
- /**
- * Throws the excpetion for when an attempt is made to read past the
- * end of the instance.
- */
- private static void throwBounds() {
- throw new IndexOutOfBoundsException("attempt to read past the end");
- }
-
- /**
- * Throws the exception for when an invalid LEB128 value is encountered
- */
- private static void throwInvalidLeb() {
- throw new RuntimeException("invalid LEB128 integer encountered");
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+/**
+ * Implementation of {@link Input} which reads the data from a
+ * byte[]
instance.
+ *
+ * Note: As per the {@link Input } interface, multi-byte
+ * reads all use little-endian order.
+ */
+public class ByteArrayInput
+ implements Input {
+
+ /** non-null; the data itself */
+ private byte[] data;
+
+ /** >= 0; current read cursor */
+ private int cursor;
+
+ /**
+ * Constructs an instance with the given data
+ *
+ * @param data non-null; data array to use for input
+ */
+ public ByteArrayInput(byte[] data) {
+ if (data == null) {
+ throw new NullPointerException("data == null");
+ }
+
+ this.data = data;
+ this.cursor = 0;
+ }
+
+ /**
+ * Gets the underlying byte[]
of this instance
+ *
+ * @return non-null; the byte[]
+ */
+ public byte[] getArray() {
+ return data;
+ }
+
+ /** {@inheritDoc} */
+ public int getCursor() {
+ return cursor;
+ }
+
+ /** {@inheritDoc} */
+ public void setCursor(int cursor) {
+ if (cursor < 0 || cursor >= data.length)
+ throw new IndexOutOfBoundsException("The provided cursor value " +
+ "is not within the bounds of this instance's data array");
+ this.cursor = cursor;
+ }
+
+ /** {@inheritDoc} */
+ public void assertCursor(int expectedCursor) {
+ if (cursor != expectedCursor) {
+ throw new ExceptionWithContext("expected cursor " +
+ expectedCursor + "; actual value: " + cursor);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public byte readByte() {
+ int readAt = cursor;
+ int end = readAt + 1;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ cursor = end;
+ return data[readAt];
+ }
+
+ /** {@inheritDoc} */
+ public int readShort() {
+ int readAt = cursor;
+ int end = readAt + 2;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ cursor = end;
+ return (int)((data[readAt] & 0xff) +
+ ((data[readAt + 1] & 0xff) << 8));
+ }
+
+ /** {@inheritDoc} */
+ public int readInt() {
+ int readAt = cursor;
+ int end = readAt + 4;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ cursor = end;
+ return (data[readAt] & 0xff) +
+ ((data[readAt + 1] & 0xff) << 8) +
+ ((data[readAt + 2] & 0xff) << 16) +
+ ((data[readAt + 3] & 0xff) << 24);
+ }
+
+ /** {@inheritDoc} */
+ public long readLong() {
+ int readAt = cursor;
+ int end = readAt + 8;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ cursor = end;
+
+ return (data[readAt] & 0xffL) |
+ ((data[readAt + 1] & 0xffL) << 8) |
+ ((data[readAt + 2] & 0xffL) << 16) |
+ ((data[readAt + 3] & 0xffL) << 24) |
+ ((data[readAt + 4] & 0xffL) << 32) |
+ ((data[readAt + 5] & 0xffL) << 40) |
+ ((data[readAt + 6] & 0xffL) << 48) |
+ ((data[readAt + 7] & 0xffL) << 58);
+ }
+
+
+ /** {@inheritDoc} */
+ public int readUnsignedOrSignedLeb128() {
+ int end = cursor;
+ int currentByteValue;
+ int result;
+
+ result = data[end++] & 0xff;
+ if (result > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
+ if (currentByteValue > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ result |= (currentByteValue & 0x7f) << 14;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ result |= (currentByteValue & 0x7f) << 21;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ if (currentByteValue > 0x0f) {
+ throwInvalidLeb();
+ }
+ result |= currentByteValue << 28;
+ }
+ }
+ }
+ } else {
+ cursor = end;
+ return result;
+ }
+
+ cursor = end;
+
+ //If the last byte is 0, then this was an unsigned value (incorrectly) written in a signed format
+ //The caller wants to know if this is the case, so we'll return the negated value instead
+ //If there was only a single byte that had a value of 0, then we would have returned in the above
+ //"else"
+ if (data[end-1] == 0) {
+ return ~result;
+ }
+ return result;
+ }
+
+
+
+
+ /** {@inheritDoc} */
+ public int readUnsignedLeb128() {
+ int end = cursor;
+ int currentByteValue;
+ int result;
+
+ result = data[end++] & 0xff;
+ if (result > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
+ if (currentByteValue > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ result |= (currentByteValue & 0x7f) << 14;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ result |= (currentByteValue & 0x7f) << 21;
+ if (currentByteValue > 0x7f) {
+ currentByteValue = data[end++] & 0xff;
+ if (currentByteValue > 0x0f) {
+ throwInvalidLeb();
+ }
+ result |= currentByteValue << 28;
+ }
+ }
+ }
+ }
+
+ cursor = end;
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public int readSignedLeb128() {
+ int end = cursor;
+ int currentByteValue;
+ int result;
+
+ result = data[end++] & 0xff;
+ if (result <= 0x7f) {
+ result = (result << 25) >> 25;
+ } else {
+ currentByteValue = data[end++] & 0xff;
+ result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
+ if (currentByteValue <= 0x7f) {
+ result = (result << 18) >> 18;
+ } else {
+ currentByteValue = data[end++] & 0xff;
+ result |= (currentByteValue & 0x7f) << 14;
+ if (currentByteValue <= 0x7f) {
+ result = (result << 11) >> 11;
+ } else {
+ currentByteValue = data[end++] & 0xff;
+ result |= (currentByteValue & 0x7f) << 21;
+ if (currentByteValue <= 0x7f) {
+ result = (result << 4) >> 4;
+ } else {
+ currentByteValue = data[end++] & 0xff;
+ if (currentByteValue > 0x0f) {
+ throwInvalidLeb();
+ }
+ result |= currentByteValue << 28;
+ }
+ }
+ }
+ }
+
+ cursor = end;
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public void read(byte[] bytes, int offset, int length) {
+ int end = cursor + length;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ System.arraycopy(data, cursor, bytes, offset, length);
+ cursor = end;
+ }
+
+ /** {@inheritDoc} */
+ public void read(byte[] bytes) {
+ int length = bytes.length;
+ int end = cursor + length;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ System.arraycopy(data, cursor, bytes, 0, length);
+ cursor = end;
+ }
+
+ /** {@inheritDoc} */
+ public byte[] readBytes(int length) {
+ int end = cursor + length;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ byte[] result = new byte[length];
+ System.arraycopy(data, cursor, result, 0, length);
+ cursor = end;
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public byte[] readNullTerminatedBytes() {
+ int startPosition = cursor;
+ while (data[cursor] != 0) {
+ cursor++;
+ if (cursor >= data.length) {
+ throwBounds();
+ }
+ }
+ int byteCount = cursor - startPosition;
+ //skip the terminating null
+ cursor++;
+
+ byte[] result = new byte[byteCount];
+ System.arraycopy(data, startPosition, result, 0, byteCount);
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public void skipBytes(int count) {
+ int end = cursor + count;
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ cursor = end;
+ }
+
+ /** {@inheritDoc} */
+ public void alignTo(int alignment) {
+ int end = AlignmentUtils.alignOffset(cursor, alignment);
+
+ if (end > data.length) {
+ throwBounds();
+ }
+
+ cursor = end;
+ }
+
+ /**
+ * Throws the excpetion for when an attempt is made to read past the
+ * end of the instance.
+ */
+ private static void throwBounds() {
+ throw new IndexOutOfBoundsException("attempt to read past the end");
+ }
+
+ /**
+ * Throws the exception for when an invalid LEB128 value is encountered
+ */
+ private static void throwInvalidLeb() {
+ throw new RuntimeException("invalid LEB128 integer encountered");
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/DebugInfoBuilder.java b/dexlib/src/main/java/org/jf/dexlib/Util/DebugInfoBuilder.java
index 8fcb93f3..b2176bb7 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/DebugInfoBuilder.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/DebugInfoBuilder.java
@@ -1,451 +1,451 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-import org.jf.dexlib.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class is intended to provide an easy to use container to build up a method's debug info. You can easily add
- * an "event" at a specific address, where an event is something like a line number, start/end local, etc.
- * The events must be added such that the code addresses increase monotonically. This matches how a parser would
- * generally behave, and is intended to increase performance.
- */
-public class DebugInfoBuilder
-{
- private static final int LINE_BASE = -4;
- private static final int LINE_RANGE = 15;
- private static final int FIRST_SPECIAL = 0x0a;
-
- private int lineStart = 0;
- private ArrayList parameterNames = new ArrayList();
- private ArrayList events = new ArrayList();
- private int lastAddress = 0;
-
- private boolean hasData;
-
- private int currentAddress;
- private int currentLine;
-
- public DebugInfoBuilder() {
- }
-
- private void checkAddress(int address) {
- if (lastAddress > address) {
- throw new RuntimeException("Cannot add an event with an address before the address of the prior event");
- }
- }
-
- public void addParameterName(String parameterName) {
- if (parameterName != null) {
- hasData = true;
- }
-
- parameterNames.add(parameterName);
- }
-
- public void addLine(int address, int line) {
- hasData = true;
-
- checkAddress(address);
-
- if (lineStart == 0) {
- lineStart = line;
- }
-
- events.add(new LineEvent(address, line));
- }
-
- public void addLocal(int address, int registerNumber, String localName, String localType) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new StartLocalEvent(address, registerNumber, localName, localType));
- }
-
- public void addLocalExtended(int address, int registerNumber, String localName, String localType,
- String signature) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new StartLocalExtendedEvent(address, registerNumber, localName, localType, signature));
- }
-
- public void addEndLocal(int address, int registerNumber) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new EndLocalEvent(address, registerNumber));
- }
-
- public void addRestartLocal(int address, int registerNumber) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new RestartLocalEvent(address, registerNumber));
- }
-
- public void addPrologue(int address) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new PrologueEvent(address));
- }
-
- public void addEpilogue(int address) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new EpilogueEvent(address));
- }
-
- public void addSetFile(int address, String fileName) {
- hasData = true;
-
- checkAddress(address);
-
- events.add(new SetFileEvent(address, fileName));
- }
-
- public int getParameterNameCount() {
- return parameterNames.size();
- }
-
- public DebugInfoItem encodeDebugInfo(DexFile dexFile) {
- if (!hasData) {
- return null;
- }
-
- ByteArrayOutput out = new ByteArrayOutput();
- StringIdItem[] parameterNamesArray = new StringIdItem[parameterNames.size()];
- ArrayList- referencedItems = new ArrayList
- ();
-
- if (lineStart == 0) {
- lineStart = 1;
- }
-
- currentLine = lineStart;
-
- for (Event event: events) {
- event.emit(dexFile, out, referencedItems);
- }
- emitEndSequence(out);
-
- int index = 0;
- for (String parameterName: parameterNames) {
- if (parameterName == null) {
- parameterNamesArray[index++] = null;
- } else {
- parameterNamesArray[index++] = StringIdItem.getInternedStringIdItem(dexFile, parameterName);
- }
- }
-
- Item[] referencedItemsArray = new Item[referencedItems.size()];
- referencedItems.toArray(referencedItemsArray);
- return DebugInfoItem.getInternedDebugInfoItem(dexFile, lineStart, parameterNamesArray, out.getArray(),
- referencedItemsArray);
- }
-
- private interface Event
- {
- int getAddress();
- void emit(DexFile dexFile, Output out, List
- referencedItems);
- }
-
- private void emitEndSequence(Output out) {
- out.writeByte(0);
- }
-
- private void emitAdvancePC(Output out, int address) {
- int addressDelta = address-currentAddress;
-
- if (addressDelta > 0) {
- out.writeByte(1);
- out.writeUnsignedLeb128(addressDelta);
- currentAddress = address;
- }
- }
-
- private void emitAdvanceLine(Output out, int lineDelta) {
- out.writeByte(2);
- out.writeSignedLeb128(lineDelta);
- }
-
- private void emitStartLocal(Output out, int registerNum) {
- out.writeByte(3);
- out.writeUnsignedLeb128(registerNum);
- out.writeByte(1);
- out.writeByte(1);
- }
-
- private void emitStartLocalExtended(Output out, int registerNum) {
- out.writeByte(4);
- out.writeUnsignedLeb128(registerNum);
- out.writeByte(1);
- out.writeByte(1);
- out.writeByte(1);
- }
-
- private void emitEndLocal(Output out, int registerNum) {
- out.writeByte(5);
- out.writeUnsignedLeb128(registerNum);
- }
-
- private void emitRestartLocal(Output out, int registerNum) {
- out.writeByte(6);
- out.writeUnsignedLeb128(registerNum);
- }
-
- private void emitSetPrologueEnd(Output out) {
- out.writeByte(7);
- }
-
- private void emitSetEpilogueBegin(Output out) {
- out.writeByte(8);
- }
-
- private void emitSetFile(Output out) {
- out.writeByte(9);
- out.writeByte(1);
- }
-
- private void emitSpecialOpcode(Output out, byte opcode) {
- out.writeByte(opcode);
- }
-
- private class LineEvent implements Event
- {
- private final int address;
- private final int line;
-
- public LineEvent(int address, int line) {
- this.address = address;
- this.line = line;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- int lineDelta = line - currentLine;
- int addressDelta = address - currentAddress;
-
- if (lineDelta < -4 || lineDelta > 10) {
- emitAdvanceLine(out, lineDelta);
- lineDelta = 0;
- }
- if (lineDelta < 2 && addressDelta > 16 || lineDelta > 1 && addressDelta > 15) {
- emitAdvancePC(out, address);
- addressDelta = 0;
- }
-
- //TODO: need to handle the case when the line delta is larger than a signed int
- emitSpecialOpcode(out, calculateSpecialOpcode(lineDelta, addressDelta));
-
- currentAddress = address;
- currentLine = line;
- }
-
- private byte calculateSpecialOpcode(int lineDelta, int addressDelta) {
- return (byte)(FIRST_SPECIAL + (addressDelta * LINE_RANGE) + (lineDelta - LINE_BASE));
- }
- }
-
- private class StartLocalEvent implements Event
- {
- private final int address;
- private final int registerNum;
- private final String localName;
- private final String localType;
-
- public StartLocalEvent(int address, int registerNum, String localName, String localType) {
- this.address = address;
- this.registerNum = registerNum;
- this.localName = localName;
- this.localType = localType;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitStartLocal(out, registerNum);
- referencedItems.add(localName==null?null:StringIdItem.getInternedStringIdItem(dexFile, localName));
- referencedItems.add(localType==null?null:TypeIdItem.getInternedTypeIdItem(dexFile,
- StringIdItem.getInternedStringIdItem(dexFile, localType)));
- }
- }
-
- private class StartLocalExtendedEvent implements Event
- {
- private final int address;
- private final int registerNum;
- private final String localName;
- private final String localType;
- private final String signature;
-
- public StartLocalExtendedEvent(int address, int registerNum, String localName, String localType,
- String signature) {
- this.address = address;
- this.registerNum = registerNum;
- this.localName = localName;
- this.localType = localType;
- this.signature = signature;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitStartLocalExtended(out, registerNum);
- if (localName != null) {
- referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, localName));
- }
- if (localType != null) {
- referencedItems.add(TypeIdItem.getInternedTypeIdItem(dexFile,
- StringIdItem.getInternedStringIdItem(dexFile, localType)));
- }
- if (signature != null) {
- referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, signature));
- }
- }
- }
-
- private class EndLocalEvent implements Event
- {
- private final int address;
- private final int registerNum;
-
- public EndLocalEvent(int address, int registerNum) {
- this.address = address;
- this.registerNum = registerNum;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitEndLocal(out, registerNum);
- }
- }
-
- private class RestartLocalEvent implements Event
- {
- private final int address;
- private final int registerNum;
-
- public RestartLocalEvent(int address, int registerNum) {
- this.address = address;
- this.registerNum = registerNum;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitRestartLocal(out, registerNum);
- }
- }
-
- private class PrologueEvent implements Event
- {
- private final int address;
-
- public PrologueEvent(int address) {
- this.address = address;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitSetPrologueEnd(out);
- }
- }
-
- private class EpilogueEvent implements Event
- {
- private final int address;
-
- public EpilogueEvent(int address) {
- this.address = address;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitSetEpilogueBegin(out);
- }
- }
-
- private class SetFileEvent implements Event
- {
- private final int address;
- private final String fileName;
-
- public SetFileEvent(int address, String fileName) {
- this.address = address;
- this.fileName = fileName;
- }
-
- public int getAddress() {
- return address;
- }
-
- public void emit(DexFile dexFile, Output out, List
- referencedItems) {
- emitAdvancePC(out, address);
- emitSetFile(out);
- if (fileName != null) {
- referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, fileName));
- }
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+import org.jf.dexlib.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is intended to provide an easy to use container to build up a method's debug info. You can easily add
+ * an "event" at a specific address, where an event is something like a line number, start/end local, etc.
+ * The events must be added such that the code addresses increase monotonically. This matches how a parser would
+ * generally behave, and is intended to increase performance.
+ */
+public class DebugInfoBuilder
+{
+ private static final int LINE_BASE = -4;
+ private static final int LINE_RANGE = 15;
+ private static final int FIRST_SPECIAL = 0x0a;
+
+ private int lineStart = 0;
+ private ArrayList parameterNames = new ArrayList();
+ private ArrayList events = new ArrayList();
+ private int lastAddress = 0;
+
+ private boolean hasData;
+
+ private int currentAddress;
+ private int currentLine;
+
+ public DebugInfoBuilder() {
+ }
+
+ private void checkAddress(int address) {
+ if (lastAddress > address) {
+ throw new RuntimeException("Cannot add an event with an address before the address of the prior event");
+ }
+ }
+
+ public void addParameterName(String parameterName) {
+ if (parameterName != null) {
+ hasData = true;
+ }
+
+ parameterNames.add(parameterName);
+ }
+
+ public void addLine(int address, int line) {
+ hasData = true;
+
+ checkAddress(address);
+
+ if (lineStart == 0) {
+ lineStart = line;
+ }
+
+ events.add(new LineEvent(address, line));
+ }
+
+ public void addLocal(int address, int registerNumber, String localName, String localType) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new StartLocalEvent(address, registerNumber, localName, localType));
+ }
+
+ public void addLocalExtended(int address, int registerNumber, String localName, String localType,
+ String signature) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new StartLocalExtendedEvent(address, registerNumber, localName, localType, signature));
+ }
+
+ public void addEndLocal(int address, int registerNumber) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new EndLocalEvent(address, registerNumber));
+ }
+
+ public void addRestartLocal(int address, int registerNumber) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new RestartLocalEvent(address, registerNumber));
+ }
+
+ public void addPrologue(int address) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new PrologueEvent(address));
+ }
+
+ public void addEpilogue(int address) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new EpilogueEvent(address));
+ }
+
+ public void addSetFile(int address, String fileName) {
+ hasData = true;
+
+ checkAddress(address);
+
+ events.add(new SetFileEvent(address, fileName));
+ }
+
+ public int getParameterNameCount() {
+ return parameterNames.size();
+ }
+
+ public DebugInfoItem encodeDebugInfo(DexFile dexFile) {
+ if (!hasData) {
+ return null;
+ }
+
+ ByteArrayOutput out = new ByteArrayOutput();
+ StringIdItem[] parameterNamesArray = new StringIdItem[parameterNames.size()];
+ ArrayList
- referencedItems = new ArrayList
- ();
+
+ if (lineStart == 0) {
+ lineStart = 1;
+ }
+
+ currentLine = lineStart;
+
+ for (Event event: events) {
+ event.emit(dexFile, out, referencedItems);
+ }
+ emitEndSequence(out);
+
+ int index = 0;
+ for (String parameterName: parameterNames) {
+ if (parameterName == null) {
+ parameterNamesArray[index++] = null;
+ } else {
+ parameterNamesArray[index++] = StringIdItem.getInternedStringIdItem(dexFile, parameterName);
+ }
+ }
+
+ Item[] referencedItemsArray = new Item[referencedItems.size()];
+ referencedItems.toArray(referencedItemsArray);
+ return DebugInfoItem.getInternedDebugInfoItem(dexFile, lineStart, parameterNamesArray, out.getArray(),
+ referencedItemsArray);
+ }
+
+ private interface Event
+ {
+ int getAddress();
+ void emit(DexFile dexFile, Output out, List
- referencedItems);
+ }
+
+ private void emitEndSequence(Output out) {
+ out.writeByte(0);
+ }
+
+ private void emitAdvancePC(Output out, int address) {
+ int addressDelta = address-currentAddress;
+
+ if (addressDelta > 0) {
+ out.writeByte(1);
+ out.writeUnsignedLeb128(addressDelta);
+ currentAddress = address;
+ }
+ }
+
+ private void emitAdvanceLine(Output out, int lineDelta) {
+ out.writeByte(2);
+ out.writeSignedLeb128(lineDelta);
+ }
+
+ private void emitStartLocal(Output out, int registerNum) {
+ out.writeByte(3);
+ out.writeUnsignedLeb128(registerNum);
+ out.writeByte(1);
+ out.writeByte(1);
+ }
+
+ private void emitStartLocalExtended(Output out, int registerNum) {
+ out.writeByte(4);
+ out.writeUnsignedLeb128(registerNum);
+ out.writeByte(1);
+ out.writeByte(1);
+ out.writeByte(1);
+ }
+
+ private void emitEndLocal(Output out, int registerNum) {
+ out.writeByte(5);
+ out.writeUnsignedLeb128(registerNum);
+ }
+
+ private void emitRestartLocal(Output out, int registerNum) {
+ out.writeByte(6);
+ out.writeUnsignedLeb128(registerNum);
+ }
+
+ private void emitSetPrologueEnd(Output out) {
+ out.writeByte(7);
+ }
+
+ private void emitSetEpilogueBegin(Output out) {
+ out.writeByte(8);
+ }
+
+ private void emitSetFile(Output out) {
+ out.writeByte(9);
+ out.writeByte(1);
+ }
+
+ private void emitSpecialOpcode(Output out, byte opcode) {
+ out.writeByte(opcode);
+ }
+
+ private class LineEvent implements Event
+ {
+ private final int address;
+ private final int line;
+
+ public LineEvent(int address, int line) {
+ this.address = address;
+ this.line = line;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ int lineDelta = line - currentLine;
+ int addressDelta = address - currentAddress;
+
+ if (lineDelta < -4 || lineDelta > 10) {
+ emitAdvanceLine(out, lineDelta);
+ lineDelta = 0;
+ }
+ if (lineDelta < 2 && addressDelta > 16 || lineDelta > 1 && addressDelta > 15) {
+ emitAdvancePC(out, address);
+ addressDelta = 0;
+ }
+
+ //TODO: need to handle the case when the line delta is larger than a signed int
+ emitSpecialOpcode(out, calculateSpecialOpcode(lineDelta, addressDelta));
+
+ currentAddress = address;
+ currentLine = line;
+ }
+
+ private byte calculateSpecialOpcode(int lineDelta, int addressDelta) {
+ return (byte)(FIRST_SPECIAL + (addressDelta * LINE_RANGE) + (lineDelta - LINE_BASE));
+ }
+ }
+
+ private class StartLocalEvent implements Event
+ {
+ private final int address;
+ private final int registerNum;
+ private final String localName;
+ private final String localType;
+
+ public StartLocalEvent(int address, int registerNum, String localName, String localType) {
+ this.address = address;
+ this.registerNum = registerNum;
+ this.localName = localName;
+ this.localType = localType;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitStartLocal(out, registerNum);
+ referencedItems.add(localName==null?null:StringIdItem.getInternedStringIdItem(dexFile, localName));
+ referencedItems.add(localType==null?null:TypeIdItem.getInternedTypeIdItem(dexFile,
+ StringIdItem.getInternedStringIdItem(dexFile, localType)));
+ }
+ }
+
+ private class StartLocalExtendedEvent implements Event
+ {
+ private final int address;
+ private final int registerNum;
+ private final String localName;
+ private final String localType;
+ private final String signature;
+
+ public StartLocalExtendedEvent(int address, int registerNum, String localName, String localType,
+ String signature) {
+ this.address = address;
+ this.registerNum = registerNum;
+ this.localName = localName;
+ this.localType = localType;
+ this.signature = signature;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitStartLocalExtended(out, registerNum);
+ if (localName != null) {
+ referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, localName));
+ }
+ if (localType != null) {
+ referencedItems.add(TypeIdItem.getInternedTypeIdItem(dexFile,
+ StringIdItem.getInternedStringIdItem(dexFile, localType)));
+ }
+ if (signature != null) {
+ referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, signature));
+ }
+ }
+ }
+
+ private class EndLocalEvent implements Event
+ {
+ private final int address;
+ private final int registerNum;
+
+ public EndLocalEvent(int address, int registerNum) {
+ this.address = address;
+ this.registerNum = registerNum;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitEndLocal(out, registerNum);
+ }
+ }
+
+ private class RestartLocalEvent implements Event
+ {
+ private final int address;
+ private final int registerNum;
+
+ public RestartLocalEvent(int address, int registerNum) {
+ this.address = address;
+ this.registerNum = registerNum;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitRestartLocal(out, registerNum);
+ }
+ }
+
+ private class PrologueEvent implements Event
+ {
+ private final int address;
+
+ public PrologueEvent(int address) {
+ this.address = address;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitSetPrologueEnd(out);
+ }
+ }
+
+ private class EpilogueEvent implements Event
+ {
+ private final int address;
+
+ public EpilogueEvent(int address) {
+ this.address = address;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitSetEpilogueBegin(out);
+ }
+ }
+
+ private class SetFileEvent implements Event
+ {
+ private final int address;
+ private final String fileName;
+
+ public SetFileEvent(int address, String fileName) {
+ this.address = address;
+ this.fileName = fileName;
+ }
+
+ public int getAddress() {
+ return address;
+ }
+
+ public void emit(DexFile dexFile, Output out, List
- referencedItems) {
+ emitAdvancePC(out, address);
+ emitSetFile(out);
+ if (fileName != null) {
+ referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, fileName));
+ }
+ }
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/EncodedValueUtils.java b/dexlib/src/main/java/org/jf/dexlib/Util/EncodedValueUtils.java
index 5d0f3d2d..8b42fdbb 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/EncodedValueUtils.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/EncodedValueUtils.java
@@ -1,143 +1,143 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-public class EncodedValueUtils {
- public static byte getRequiredBytesForSignedIntegralValue(long value) {
- /*
- * Figure out how many bits are needed to represent the value,
- * including a sign bit: The bit count is subtracted from 65
- * and not 64 to account for the sign bit. The xor operation
- * has the effect of leaving non-negative values alone and
- * unary complementing negative values (so that a leading zero
- * count always returns a useful number for our present
- * purpose).
- */
- int requiredBits =
- 65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
-
- // Round up the requiredBits to a number of bytes.
- return (byte)((requiredBits + 0x07) >> 3);
- }
-
- public static long decodeSignedIntegralValue(byte[] bytes) {
- long value = 0;
- for (int i = 0; i < bytes.length; i++) {
- value |= (((long)(bytes[i] & 0xFF)) << (i * 8));
- }
-
- int shift = (8 - bytes.length) * 8;
- return value << shift >> shift;
- }
-
- public static byte[] encodeSignedIntegralValue(long value) {
- int requiredBytes = getRequiredBytesForSignedIntegralValue(value);
-
- byte[] bytes = new byte[requiredBytes];
-
- for (int i = 0; i < requiredBytes; i++) {
- bytes[i] = (byte) value;
- value >>= 8;
- }
- return bytes;
- }
-
-
-
-
-
- public static byte getRequiredBytesForUnsignedIntegralValue(long value) {
- // Figure out how many bits are needed to represent the value.
- int requiredBits = 64 - Long.numberOfLeadingZeros(value);
- if (requiredBits == 0) {
- requiredBits = 1;
- }
-
- // Round up the requiredBits to a number of bytes.
- return (byte)((requiredBits + 0x07) >> 3);
- }
-
- public static long decodeUnsignedIntegralValue(byte[] bytes) {
- long value = 0;
- for (int i = 0; i < bytes.length; i++) {
- value |= (((long)(bytes[i] & 0xFF)) << i * 8);
- }
- return value;
- }
-
- public static byte[] encodeUnsignedIntegralValue(long value) {
- int requiredBytes = getRequiredBytesForUnsignedIntegralValue(value);
-
- byte[] bytes = new byte[requiredBytes];
-
- for (int i = 0; i < requiredBytes; i++) {
- bytes[i] = (byte) value;
- value >>= 8;
- }
- return bytes;
- }
-
-
-
-
-
- public static int getRequiredBytesForRightZeroExtendedValue(long value) {
- // Figure out how many bits are needed to represent the value.
- int requiredBits = 64 - Long.numberOfTrailingZeros(value);
- if (requiredBits == 0) {
- requiredBits = 1;
- }
-
- // Round up the requiredBits to a number of bytes.
- return (requiredBits + 0x07) >> 3;
- }
-
- public static long decodeRightZeroExtendedValue(byte[] bytes) {
- long value = 0;
- for (int i = 0; i < bytes.length; i++) {
- value |= (((long)(bytes[i] & 0xFF)) << (i * 8));
- }
- return value << (8 - bytes.length) * 8;
- }
-
- public static byte[] encodeRightZeroExtendedValue(long value) {
- int requiredBytes = getRequiredBytesForRightZeroExtendedValue(value);
-
- // Scootch the first bits to be written down to the low-order bits.
- value >>= 64 - (requiredBytes * 8);
-
- byte[] bytes = new byte[requiredBytes];
-
- for(int i = 0; i < requiredBytes; i++) {
- bytes[i] = (byte)value;
- value >>= 8;
- }
- return bytes;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+public class EncodedValueUtils {
+ public static byte getRequiredBytesForSignedIntegralValue(long value) {
+ /*
+ * Figure out how many bits are needed to represent the value,
+ * including a sign bit: The bit count is subtracted from 65
+ * and not 64 to account for the sign bit. The xor operation
+ * has the effect of leaving non-negative values alone and
+ * unary complementing negative values (so that a leading zero
+ * count always returns a useful number for our present
+ * purpose).
+ */
+ int requiredBits =
+ 65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
+
+ // Round up the requiredBits to a number of bytes.
+ return (byte)((requiredBits + 0x07) >> 3);
+ }
+
+ public static long decodeSignedIntegralValue(byte[] bytes) {
+ long value = 0;
+ for (int i = 0; i < bytes.length; i++) {
+ value |= (((long)(bytes[i] & 0xFF)) << (i * 8));
+ }
+
+ int shift = (8 - bytes.length) * 8;
+ return value << shift >> shift;
+ }
+
+ public static byte[] encodeSignedIntegralValue(long value) {
+ int requiredBytes = getRequiredBytesForSignedIntegralValue(value);
+
+ byte[] bytes = new byte[requiredBytes];
+
+ for (int i = 0; i < requiredBytes; i++) {
+ bytes[i] = (byte) value;
+ value >>= 8;
+ }
+ return bytes;
+ }
+
+
+
+
+
+ public static byte getRequiredBytesForUnsignedIntegralValue(long value) {
+ // Figure out how many bits are needed to represent the value.
+ int requiredBits = 64 - Long.numberOfLeadingZeros(value);
+ if (requiredBits == 0) {
+ requiredBits = 1;
+ }
+
+ // Round up the requiredBits to a number of bytes.
+ return (byte)((requiredBits + 0x07) >> 3);
+ }
+
+ public static long decodeUnsignedIntegralValue(byte[] bytes) {
+ long value = 0;
+ for (int i = 0; i < bytes.length; i++) {
+ value |= (((long)(bytes[i] & 0xFF)) << i * 8);
+ }
+ return value;
+ }
+
+ public static byte[] encodeUnsignedIntegralValue(long value) {
+ int requiredBytes = getRequiredBytesForUnsignedIntegralValue(value);
+
+ byte[] bytes = new byte[requiredBytes];
+
+ for (int i = 0; i < requiredBytes; i++) {
+ bytes[i] = (byte) value;
+ value >>= 8;
+ }
+ return bytes;
+ }
+
+
+
+
+
+ public static int getRequiredBytesForRightZeroExtendedValue(long value) {
+ // Figure out how many bits are needed to represent the value.
+ int requiredBits = 64 - Long.numberOfTrailingZeros(value);
+ if (requiredBits == 0) {
+ requiredBits = 1;
+ }
+
+ // Round up the requiredBits to a number of bytes.
+ return (requiredBits + 0x07) >> 3;
+ }
+
+ public static long decodeRightZeroExtendedValue(byte[] bytes) {
+ long value = 0;
+ for (int i = 0; i < bytes.length; i++) {
+ value |= (((long)(bytes[i] & 0xFF)) << (i * 8));
+ }
+ return value << (8 - bytes.length) * 8;
+ }
+
+ public static byte[] encodeRightZeroExtendedValue(long value) {
+ int requiredBytes = getRequiredBytesForRightZeroExtendedValue(value);
+
+ // Scootch the first bits to be written down to the low-order bits.
+ value >>= 64 - (requiredBytes * 8);
+
+ byte[] bytes = new byte[requiredBytes];
+
+ for(int i = 0; i < requiredBytes; i++) {
+ bytes[i] = (byte)value;
+ value >>= 8;
+ }
+ return bytes;
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/Input.java b/dexlib/src/main/java/org/jf/dexlib/Util/Input.java
index 463ed98b..37fd09ce 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/Input.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/Input.java
@@ -1,167 +1,167 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-/**
- * Interface for a source for binary input. This is similar to
- *
java.util.DataInput
, but no IOExceptions
- * are declared, and multibyte input is defined to be little-endian.
- */
-public interface Input {
- /**
- * Gets the current cursor position. This is the same as the number of
- * bytes read from this instance.
- *
- * @return >= 0; the cursor position
- */
- public int getCursor();
-
- /**
- * Sets the current cursor position.
- *
- * @return >= 0; the cursor position
- */
- public void setCursor(int cursor);
-
- /**
- * Asserts that the cursor is the given value.
- *
- * @param expectedCursor the expected cursor value
- * @throws RuntimeException thrown if getCursor() !=
- * expectedCursor
- */
- public void assertCursor(int expectedCursor);
-
- /**
- * Reads a byte
from this instance.
- *
- * @return the byte value that was read
- */
- public byte readByte();
-
- /**
- * Reads a short
from this instance.
- *
- * @return the short value that was read, as an int
- */
- public int readShort();
-
- /**
- * Reads an int
from this instance.
- *
- * @return the unsigned int value that was read
- */
- public int readInt();
-
- /**
- * Reads a long
from this instance.
- *
- * @return the long value that was read
- */
- public long readLong();
-
-
- /**
- * Reads a DWARFv3-style signed LEB128 integer. For details,
- * see the "Dalvik Executable Format" document or DWARF v3 section
- * 7.6.
- *
- * @return the integer value that was read
- */
- public int readSignedLeb128();
-
- /**
- * Reads a DWARFv3-style unsigned LEB128 integer. For details,
- * see the "Dalvik Executable Format" document or DWARF v3 section
- * 7.6.
- *
- * @return the integer value that was read
- */
- public int readUnsignedLeb128();
-
-
- /**
- * Reads a unsigned value as a DWARFv3-style LEB128 integer. It specifically
- * checks for the case when the value was incorrectly formatted as a signed
- * LEB128, and returns the appropriate unsigned value, but negated
- * @return If the value was formatted as a ULEB128, it returns the actual unsigned
- * value. Otherwise, if the value was formatted as a signed LEB128, it negates the
- * "correct" unsigned value and returns that
- */
- public int readUnsignedOrSignedLeb128();
-
- /**
- * reads a byte[]
from this instance.
- *
- * @param bytes non-null; the buffer to read the data into
- * @param offset >= 0; offset into bytes
for the first
- * byte to write
- * @param length >= 0; number of bytes to read
- */
- public void read(byte[] bytes, int offset, int length);
-
- /**
- * reads a byte[]
from this instance. This is just
- * a convenient shorthand for read(bytes, 0, bytes.length)
.
- *
- * @param bytes non-null; the buffer to read the data into
- */
- public void read(byte[] bytes);
-
-
- /**
- * reads a byte[]
from this instance
- *
- * @param length >= 0; number of bytes to read
- * @return a byte array containing length
bytes
- */
- public byte[] readBytes(int length);
-
- /**
- * reads a byte[]
from this instance, from the current cursor up to but not including
- * the next null (0) byte. The terminating null byte is read and discarded, so that after the read,
- * the cursor is positioned at the byte immediately after the terminating null
- */
- public byte[] readNullTerminatedBytes();
-
- /**
- * Skips the given number of bytes.
- *
- * @param count >= 0; the number of bytes to skip
- */
- public void skipBytes(int count);
-
- /**
- * Skip extra bytes if necessary to force alignment of the output
- * cursor as given.
- *
- * @param alignment > 0; the alignment; must be a power of two
- */
- public void alignTo(int alignment);
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+/**
+ * Interface for a source for binary input. This is similar to
+ * java.util.DataInput
, but no IOExceptions
+ * are declared, and multibyte input is defined to be little-endian.
+ */
+public interface Input {
+ /**
+ * Gets the current cursor position. This is the same as the number of
+ * bytes read from this instance.
+ *
+ * @return >= 0; the cursor position
+ */
+ public int getCursor();
+
+ /**
+ * Sets the current cursor position.
+ *
+ * @return >= 0; the cursor position
+ */
+ public void setCursor(int cursor);
+
+ /**
+ * Asserts that the cursor is the given value.
+ *
+ * @param expectedCursor the expected cursor value
+ * @throws RuntimeException thrown if getCursor() !=
+ * expectedCursor
+ */
+ public void assertCursor(int expectedCursor);
+
+ /**
+ * Reads a byte
from this instance.
+ *
+ * @return the byte value that was read
+ */
+ public byte readByte();
+
+ /**
+ * Reads a short
from this instance.
+ *
+ * @return the short value that was read, as an int
+ */
+ public int readShort();
+
+ /**
+ * Reads an int
from this instance.
+ *
+ * @return the unsigned int value that was read
+ */
+ public int readInt();
+
+ /**
+ * Reads a long
from this instance.
+ *
+ * @return the long value that was read
+ */
+ public long readLong();
+
+
+ /**
+ * Reads a DWARFv3-style signed LEB128 integer. For details,
+ * see the "Dalvik Executable Format" document or DWARF v3 section
+ * 7.6.
+ *
+ * @return the integer value that was read
+ */
+ public int readSignedLeb128();
+
+ /**
+ * Reads a DWARFv3-style unsigned LEB128 integer. For details,
+ * see the "Dalvik Executable Format" document or DWARF v3 section
+ * 7.6.
+ *
+ * @return the integer value that was read
+ */
+ public int readUnsignedLeb128();
+
+
+ /**
+ * Reads a unsigned value as a DWARFv3-style LEB128 integer. It specifically
+ * checks for the case when the value was incorrectly formatted as a signed
+ * LEB128, and returns the appropriate unsigned value, but negated
+ * @return If the value was formatted as a ULEB128, it returns the actual unsigned
+ * value. Otherwise, if the value was formatted as a signed LEB128, it negates the
+ * "correct" unsigned value and returns that
+ */
+ public int readUnsignedOrSignedLeb128();
+
+ /**
+ * reads a byte[]
from this instance.
+ *
+ * @param bytes non-null; the buffer to read the data into
+ * @param offset >= 0; offset into bytes
for the first
+ * byte to write
+ * @param length >= 0; number of bytes to read
+ */
+ public void read(byte[] bytes, int offset, int length);
+
+ /**
+ * reads a byte[]
from this instance. This is just
+ * a convenient shorthand for read(bytes, 0, bytes.length)
.
+ *
+ * @param bytes non-null; the buffer to read the data into
+ */
+ public void read(byte[] bytes);
+
+
+ /**
+ * reads a byte[]
from this instance
+ *
+ * @param length >= 0; number of bytes to read
+ * @return a byte array containing length
bytes
+ */
+ public byte[] readBytes(int length);
+
+ /**
+ * reads a byte[]
from this instance, from the current cursor up to but not including
+ * the next null (0) byte. The terminating null byte is read and discarded, so that after the read,
+ * the cursor is positioned at the byte immediately after the terminating null
+ */
+ public byte[] readNullTerminatedBytes();
+
+ /**
+ * Skips the given number of bytes.
+ *
+ * @param count >= 0; the number of bytes to skip
+ */
+ public void skipBytes(int count);
+
+ /**
+ * Skip extra bytes if necessary to force alignment of the output
+ * cursor as given.
+ *
+ * @param alignment > 0; the alignment; must be a power of two
+ */
+ public void alignTo(int alignment);
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/Pair.java b/dexlib/src/main/java/org/jf/dexlib/Util/Pair.java
index c0fb468a..490049cd 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/Pair.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/Pair.java
@@ -1,40 +1,40 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-public class Pair {
- public final A first;
- public final B second;
-
- public Pair(A first, B second) {
- this.first = first;
- this.second = second;
- }
-}
-
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+public class Pair {
+ public final A first;
+ public final B second;
+
+ public Pair(A first, B second) {
+ this.first = first;
+ this.second = second;
+ }
+}
+
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/TryListBuilder.java b/dexlib/src/main/java/org/jf/dexlib/Util/TryListBuilder.java
index 65ea048c..8cb572ea 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/TryListBuilder.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/TryListBuilder.java
@@ -1,347 +1,347 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-import org.jf.dexlib.CodeItem;
-import org.jf.dexlib.TypeIdItem;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-
-public class TryListBuilder
-{
- /*TODO: add logic to merge adjacent, identical try blocks, and remove superflous handlers
- Also provide a "strict" mode, where the above isn't performed, which will be useful to be able to
- exactly reproduce the original .dex file (for testing/verification purposes)*/
-
-
- private TryRange firstTryRange = new TryRange(0,0);
- private TryRange lastTryRange = new TryRange(0,0);
-
- public TryListBuilder() {
- firstTryRange.next = lastTryRange;
- lastTryRange.previous = firstTryRange;
- }
-
- private class TryRange
- {
- public TryRange previous = null;
- public TryRange next = null;
-
- public int startAddress;
- public int endAddress;
- public LinkedList handlers;
-
- public int catchAllHandlerAddress;
-
- public TryRange(int startAddress, int endAddress) {
- this.startAddress = startAddress;
- this.endAddress = endAddress;
- this.handlers = new LinkedList();
- this.previous = null;
- this.next = null;
- catchAllHandlerAddress = -1;
- }
-
- public void append(TryRange tryRange) {
- /*we use a dummy last item, so this.next will always
- have a value*/
- this.next.previous = tryRange;
- tryRange.next = this.next;
-
- this.next = tryRange;
- tryRange.previous = this;
- }
-
- public void prepend(TryRange tryRange){
- /*we use a dummy first item, so this.previous will always
- have a value*/
- this.previous.next = tryRange;
- tryRange.previous = this.previous;
-
- this.previous = tryRange;
- tryRange.next = this;
- }
-
- /**
- * This splits the current range into two ranges at the given
- * address. The existing range will be shortened to the first
- * half, and a new range will be created and returned for the
- * 2nd half.
- * @param address The address to split at
- * @return The 2nd half of the
- */
- public TryRange split(int address) {
- //this is a private class, so address is assumed
- //to be valid
-
- TryRange tryRange = new TryRange(address, endAddress);
- tryRange.catchAllHandlerAddress = this.catchAllHandlerAddress;
- tryRange.handlers.addAll(this.handlers);
- append(tryRange);
-
- this.endAddress = address;
-
- return tryRange;
- }
-
- public void appendHandler(Handler handler) {
- handlers.addLast(handler);
- }
-
- public void prependHandler(Handler handler) {
- handlers.addFirst(handler);
- }
- }
-
- private class Handler
- {
- public final TypeIdItem type;
- public final int handlerAddress;
-
- public Handler(TypeIdItem type, int handlerAddress) {
- this.type = type;
- this.handlerAddress = handlerAddress;
- }
- }
-
- public Pair, List> encodeTries() {
- if (firstTryRange.next == lastTryRange) {
- return new Pair, List>(null, null);
- }
-
- ArrayList tries = new ArrayList();
- ArrayList handlers = new ArrayList();
-
- HashMap handlerDict =
- new HashMap();
-
- TryRange tryRange = firstTryRange.next;
-
- while (tryRange != lastTryRange) {
- CodeItem.EncodedTypeAddrPair[] encodedTypeAddrPairs =
- new CodeItem.EncodedTypeAddrPair[tryRange.handlers.size()];
-
- int index = 0;
- for (Handler handler: tryRange.handlers) {
- CodeItem.EncodedTypeAddrPair encodedTypeAddrPair = new CodeItem.EncodedTypeAddrPair(
- handler.type,
- handler.handlerAddress);
- encodedTypeAddrPairs[index++] = encodedTypeAddrPair;
- }
-
- CodeItem.EncodedCatchHandler encodedCatchHandler = new CodeItem.EncodedCatchHandler(
- encodedTypeAddrPairs,
- tryRange.catchAllHandlerAddress);
- CodeItem.EncodedCatchHandler internedEncodedCatchHandler = handlerDict.get(encodedCatchHandler);
- if (internedEncodedCatchHandler == null) {
- handlerDict.put(encodedCatchHandler, encodedCatchHandler);
- handlers.add(encodedCatchHandler);
- } else {
- encodedCatchHandler = internedEncodedCatchHandler;
- }
-
- CodeItem.TryItem tryItem = new CodeItem.TryItem(
- tryRange.startAddress,
- tryRange.endAddress - tryRange.startAddress,
- encodedCatchHandler);
- tries.add(tryItem);
-
- tryRange = tryRange.next;
- }
-
- return new Pair, List>(tries, handlers);
- }
-
- public void addCatchAllHandler(int startAddress, int endAddress, int handlerAddress) {
- TryRange startRange;
- TryRange endRange;
-
- Pair ranges = getBoundingRanges(startAddress, endAddress);
- startRange = ranges.first;
- endRange = ranges.second;
-
- int previousEnd = startAddress;
- TryRange tryRange = startRange;
-
- /*Now we have the start and end ranges that exactly match the start and end
- of the range being added. We need to iterate over all the ranges from the start
- to end range inclusively, and append the handler to the end of each range's handler
- list. We also need to create a new range for any "holes" in the existing ranges*/
- do
- {
- //is there a hole? If so, add a new range to fill the hole
- if (tryRange.startAddress > previousEnd) {
- TryRange newRange = new TryRange(previousEnd, tryRange.startAddress);
- tryRange.prepend(newRange);
- tryRange = newRange;
- }
-
- if (tryRange.catchAllHandlerAddress == -1) {
- tryRange.catchAllHandlerAddress = handlerAddress;
- }
-
- previousEnd = tryRange.endAddress;
- tryRange = tryRange.next;
- } while (tryRange.previous != endRange);
- }
-
- public Pair getBoundingRanges(int startAddress, int endAddress) {
- TryRange startRange = null;
- TryRange endRange = null;
-
- TryRange tryRange = firstTryRange.next;
- while (tryRange != lastTryRange) {
- if (startAddress == tryRange.startAddress) {
- //|-----|
- //^------
- /*Bam. We hit the start of the range right on the head*/
- startRange = tryRange;
- break;
- } else if (startAddress > tryRange.startAddress && startAddress < tryRange.endAddress) {
- //|-----|
- // ^----
- /*Almost. The start of the range being added is in the middle
- of an existing try range. We need to split the existing range
- at the start address of the range being added*/
- startRange = tryRange.split(startAddress);
- break;
- }else if (startAddress < tryRange.startAddress) {
- if (endAddress <= tryRange.startAddress) {
- // |-----|
- //^--^
- /*Oops, totally too far! The new range doesn't overlap any existing
- ones, so we just add it and return*/
- startRange = new TryRange(startAddress, endAddress);
- tryRange.prepend(startRange);
- return new Pair(startRange, startRange);
- } else {
- // |-----|
- //^---------
- /*Oops, too far! We've passed the start of the range being added, but
- the new range does overlap this one. We need to add a new range just
- before this one*/
- startRange = new TryRange(startAddress, tryRange.startAddress);
- tryRange.prepend(startRange);
- break;
- }
- }
-
- tryRange = tryRange.next;
- }
-
- //|-----|
- // ^-----
- /*Either the list of tries is blank, or all the tries in the list
- end before the range being added starts. In either case, we just need
- to add a new range at the end of the list*/
- if (startRange == null) {
- startRange = new TryRange(startAddress, endAddress);
- lastTryRange.prepend(startRange);
- return new Pair(startRange, startRange);
- }
-
- tryRange = startRange;
- while (tryRange != lastTryRange) {
- if (tryRange.endAddress == endAddress) {
- //|-----|
- //------^
- /*Bam! We hit the end right on the head.*/
- endRange = tryRange;
- break;
- } else if (tryRange.startAddress < endAddress && tryRange.endAddress > endAddress) {
- //|-----|
- //--^
- /*Almost. The range being added ends in the middle of an
- existing range. We need to split the existing range
- at the end of the range being added.*/
- tryRange.split(endAddress);
- endRange = tryRange;
- break;
- } else if (tryRange.startAddress >= endAddress) {
- //|-----| |-----|
- //-----------^
- /*Oops, too far! The current range starts after the range being added
- ends. We need to create a new range that starts at the end of the
- previous range, and ends at the end of the range being added*/
- endRange = new TryRange(tryRange.previous.endAddress, endAddress);
- tryRange.prepend(endRange);
- break;
- }
- tryRange = tryRange.next;
- }
-
- //|-----|
- //--------^
- /*The last range in the list ended before the end of the range being added.
- We need to add a new range that starts at the end of the last range in the
- list, and ends at the end of the range being added.*/
- if (endRange == null) {
- endRange = new TryRange(lastTryRange.previous.endAddress, endAddress);
- lastTryRange.prepend(endRange);
- }
-
- return new Pair(startRange, endRange);
- }
-
- public void addHandler(TypeIdItem type, int startAddress, int endAddress, int handlerAddress) {
- TryRange startRange;
- TryRange endRange;
-
- //TODO: need to check for pre-existing exception types in the handler list?
-
- Pair ranges = getBoundingRanges(startAddress, endAddress);
- startRange = ranges.first;
- endRange = ranges.second;
- Handler handler = new Handler(type, handlerAddress);
-
- int previousEnd = startAddress;
- TryRange tryRange = startRange;
-
- /*Now we have the start and end ranges that exactly match the start and end
- of the range being added. We need to iterate over all the ranges from the start
- to end range inclusively, and append the handler to the end of each range's handler
- list. We also need to create a new range for any "holes" in the existing ranges*/
- do
- {
- //is there a hole? If so, add a new range to fill the hole
- if (tryRange.startAddress > previousEnd) {
- TryRange newRange = new TryRange(previousEnd, tryRange.startAddress);
- tryRange.prepend(newRange);
- tryRange = newRange;
- }
-
- tryRange.appendHandler(handler);
- previousEnd = tryRange.endAddress;
- tryRange = tryRange.next;
- } while (tryRange.previous != endRange);
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+import org.jf.dexlib.CodeItem;
+import org.jf.dexlib.TypeIdItem;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+public class TryListBuilder
+{
+ /*TODO: add logic to merge adjacent, identical try blocks, and remove superflous handlers
+ Also provide a "strict" mode, where the above isn't performed, which will be useful to be able to
+ exactly reproduce the original .dex file (for testing/verification purposes)*/
+
+
+ private TryRange firstTryRange = new TryRange(0,0);
+ private TryRange lastTryRange = new TryRange(0,0);
+
+ public TryListBuilder() {
+ firstTryRange.next = lastTryRange;
+ lastTryRange.previous = firstTryRange;
+ }
+
+ private class TryRange
+ {
+ public TryRange previous = null;
+ public TryRange next = null;
+
+ public int startAddress;
+ public int endAddress;
+ public LinkedList handlers;
+
+ public int catchAllHandlerAddress;
+
+ public TryRange(int startAddress, int endAddress) {
+ this.startAddress = startAddress;
+ this.endAddress = endAddress;
+ this.handlers = new LinkedList();
+ this.previous = null;
+ this.next = null;
+ catchAllHandlerAddress = -1;
+ }
+
+ public void append(TryRange tryRange) {
+ /*we use a dummy last item, so this.next will always
+ have a value*/
+ this.next.previous = tryRange;
+ tryRange.next = this.next;
+
+ this.next = tryRange;
+ tryRange.previous = this;
+ }
+
+ public void prepend(TryRange tryRange){
+ /*we use a dummy first item, so this.previous will always
+ have a value*/
+ this.previous.next = tryRange;
+ tryRange.previous = this.previous;
+
+ this.previous = tryRange;
+ tryRange.next = this;
+ }
+
+ /**
+ * This splits the current range into two ranges at the given
+ * address. The existing range will be shortened to the first
+ * half, and a new range will be created and returned for the
+ * 2nd half.
+ * @param address The address to split at
+ * @return The 2nd half of the
+ */
+ public TryRange split(int address) {
+ //this is a private class, so address is assumed
+ //to be valid
+
+ TryRange tryRange = new TryRange(address, endAddress);
+ tryRange.catchAllHandlerAddress = this.catchAllHandlerAddress;
+ tryRange.handlers.addAll(this.handlers);
+ append(tryRange);
+
+ this.endAddress = address;
+
+ return tryRange;
+ }
+
+ public void appendHandler(Handler handler) {
+ handlers.addLast(handler);
+ }
+
+ public void prependHandler(Handler handler) {
+ handlers.addFirst(handler);
+ }
+ }
+
+ private class Handler
+ {
+ public final TypeIdItem type;
+ public final int handlerAddress;
+
+ public Handler(TypeIdItem type, int handlerAddress) {
+ this.type = type;
+ this.handlerAddress = handlerAddress;
+ }
+ }
+
+ public Pair, List> encodeTries() {
+ if (firstTryRange.next == lastTryRange) {
+ return new Pair, List>(null, null);
+ }
+
+ ArrayList tries = new ArrayList();
+ ArrayList handlers = new ArrayList();
+
+ HashMap handlerDict =
+ new HashMap();
+
+ TryRange tryRange = firstTryRange.next;
+
+ while (tryRange != lastTryRange) {
+ CodeItem.EncodedTypeAddrPair[] encodedTypeAddrPairs =
+ new CodeItem.EncodedTypeAddrPair[tryRange.handlers.size()];
+
+ int index = 0;
+ for (Handler handler: tryRange.handlers) {
+ CodeItem.EncodedTypeAddrPair encodedTypeAddrPair = new CodeItem.EncodedTypeAddrPair(
+ handler.type,
+ handler.handlerAddress);
+ encodedTypeAddrPairs[index++] = encodedTypeAddrPair;
+ }
+
+ CodeItem.EncodedCatchHandler encodedCatchHandler = new CodeItem.EncodedCatchHandler(
+ encodedTypeAddrPairs,
+ tryRange.catchAllHandlerAddress);
+ CodeItem.EncodedCatchHandler internedEncodedCatchHandler = handlerDict.get(encodedCatchHandler);
+ if (internedEncodedCatchHandler == null) {
+ handlerDict.put(encodedCatchHandler, encodedCatchHandler);
+ handlers.add(encodedCatchHandler);
+ } else {
+ encodedCatchHandler = internedEncodedCatchHandler;
+ }
+
+ CodeItem.TryItem tryItem = new CodeItem.TryItem(
+ tryRange.startAddress,
+ tryRange.endAddress - tryRange.startAddress,
+ encodedCatchHandler);
+ tries.add(tryItem);
+
+ tryRange = tryRange.next;
+ }
+
+ return new Pair, List>(tries, handlers);
+ }
+
+ public void addCatchAllHandler(int startAddress, int endAddress, int handlerAddress) {
+ TryRange startRange;
+ TryRange endRange;
+
+ Pair ranges = getBoundingRanges(startAddress, endAddress);
+ startRange = ranges.first;
+ endRange = ranges.second;
+
+ int previousEnd = startAddress;
+ TryRange tryRange = startRange;
+
+ /*Now we have the start and end ranges that exactly match the start and end
+ of the range being added. We need to iterate over all the ranges from the start
+ to end range inclusively, and append the handler to the end of each range's handler
+ list. We also need to create a new range for any "holes" in the existing ranges*/
+ do
+ {
+ //is there a hole? If so, add a new range to fill the hole
+ if (tryRange.startAddress > previousEnd) {
+ TryRange newRange = new TryRange(previousEnd, tryRange.startAddress);
+ tryRange.prepend(newRange);
+ tryRange = newRange;
+ }
+
+ if (tryRange.catchAllHandlerAddress == -1) {
+ tryRange.catchAllHandlerAddress = handlerAddress;
+ }
+
+ previousEnd = tryRange.endAddress;
+ tryRange = tryRange.next;
+ } while (tryRange.previous != endRange);
+ }
+
+ public Pair getBoundingRanges(int startAddress, int endAddress) {
+ TryRange startRange = null;
+ TryRange endRange = null;
+
+ TryRange tryRange = firstTryRange.next;
+ while (tryRange != lastTryRange) {
+ if (startAddress == tryRange.startAddress) {
+ //|-----|
+ //^------
+ /*Bam. We hit the start of the range right on the head*/
+ startRange = tryRange;
+ break;
+ } else if (startAddress > tryRange.startAddress && startAddress < tryRange.endAddress) {
+ //|-----|
+ // ^----
+ /*Almost. The start of the range being added is in the middle
+ of an existing try range. We need to split the existing range
+ at the start address of the range being added*/
+ startRange = tryRange.split(startAddress);
+ break;
+ }else if (startAddress < tryRange.startAddress) {
+ if (endAddress <= tryRange.startAddress) {
+ // |-----|
+ //^--^
+ /*Oops, totally too far! The new range doesn't overlap any existing
+ ones, so we just add it and return*/
+ startRange = new TryRange(startAddress, endAddress);
+ tryRange.prepend(startRange);
+ return new Pair(startRange, startRange);
+ } else {
+ // |-----|
+ //^---------
+ /*Oops, too far! We've passed the start of the range being added, but
+ the new range does overlap this one. We need to add a new range just
+ before this one*/
+ startRange = new TryRange(startAddress, tryRange.startAddress);
+ tryRange.prepend(startRange);
+ break;
+ }
+ }
+
+ tryRange = tryRange.next;
+ }
+
+ //|-----|
+ // ^-----
+ /*Either the list of tries is blank, or all the tries in the list
+ end before the range being added starts. In either case, we just need
+ to add a new range at the end of the list*/
+ if (startRange == null) {
+ startRange = new TryRange(startAddress, endAddress);
+ lastTryRange.prepend(startRange);
+ return new Pair(startRange, startRange);
+ }
+
+ tryRange = startRange;
+ while (tryRange != lastTryRange) {
+ if (tryRange.endAddress == endAddress) {
+ //|-----|
+ //------^
+ /*Bam! We hit the end right on the head.*/
+ endRange = tryRange;
+ break;
+ } else if (tryRange.startAddress < endAddress && tryRange.endAddress > endAddress) {
+ //|-----|
+ //--^
+ /*Almost. The range being added ends in the middle of an
+ existing range. We need to split the existing range
+ at the end of the range being added.*/
+ tryRange.split(endAddress);
+ endRange = tryRange;
+ break;
+ } else if (tryRange.startAddress >= endAddress) {
+ //|-----| |-----|
+ //-----------^
+ /*Oops, too far! The current range starts after the range being added
+ ends. We need to create a new range that starts at the end of the
+ previous range, and ends at the end of the range being added*/
+ endRange = new TryRange(tryRange.previous.endAddress, endAddress);
+ tryRange.prepend(endRange);
+ break;
+ }
+ tryRange = tryRange.next;
+ }
+
+ //|-----|
+ //--------^
+ /*The last range in the list ended before the end of the range being added.
+ We need to add a new range that starts at the end of the last range in the
+ list, and ends at the end of the range being added.*/
+ if (endRange == null) {
+ endRange = new TryRange(lastTryRange.previous.endAddress, endAddress);
+ lastTryRange.prepend(endRange);
+ }
+
+ return new Pair(startRange, endRange);
+ }
+
+ public void addHandler(TypeIdItem type, int startAddress, int endAddress, int handlerAddress) {
+ TryRange startRange;
+ TryRange endRange;
+
+ //TODO: need to check for pre-existing exception types in the handler list?
+
+ Pair ranges = getBoundingRanges(startAddress, endAddress);
+ startRange = ranges.first;
+ endRange = ranges.second;
+ Handler handler = new Handler(type, handlerAddress);
+
+ int previousEnd = startAddress;
+ TryRange tryRange = startRange;
+
+ /*Now we have the start and end ranges that exactly match the start and end
+ of the range being added. We need to iterate over all the ranges from the start
+ to end range inclusively, and append the handler to the end of each range's handler
+ list. We also need to create a new range for any "holes" in the existing ranges*/
+ do
+ {
+ //is there a hole? If so, add a new range to fill the hole
+ if (tryRange.startAddress > previousEnd) {
+ TryRange newRange = new TryRange(previousEnd, tryRange.startAddress);
+ tryRange.prepend(newRange);
+ tryRange = newRange;
+ }
+
+ tryRange.appendHandler(handler);
+ previousEnd = tryRange.endAddress;
+ tryRange = tryRange.next;
+ } while (tryRange.previous != endRange);
+ }
+}
diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/TypeUtils.java b/dexlib/src/main/java/org/jf/dexlib/Util/TypeUtils.java
index 68a9fd5b..26370a5a 100644
--- a/dexlib/src/main/java/org/jf/dexlib/Util/TypeUtils.java
+++ b/dexlib/src/main/java/org/jf/dexlib/Util/TypeUtils.java
@@ -1,61 +1,61 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.Util;
-
-import org.jf.dexlib.DexFile;
-import org.jf.dexlib.EncodedValue.*;
-
-public class TypeUtils
-{
- public static EncodedValue makeDefaultValueForType(DexFile dexFile, String type) {
- EncodedValue subField;
- switch (type.charAt(0)) {
- case 'Z':
- return BooleanEncodedValue.FalseValue;
- case 'B':
- return new ByteEncodedValue((byte)0);
- case 'S':
- return new ShortEncodedValue((short)0);
- case 'C':
- return new CharEncodedValue((char)0);
- case 'I':
- return new IntEncodedValue(0);
- case 'J':
- return new LongEncodedValue(0);
- case 'F':
- return new FloatEncodedValue(0);
- case 'D':
- return new DoubleEncodedValue(0);
- case 'L':
- case '[':
- return NullEncodedValue.NullValue;
- }
- return null;
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.Util;
+
+import org.jf.dexlib.DexFile;
+import org.jf.dexlib.EncodedValue.*;
+
+public class TypeUtils
+{
+ public static EncodedValue makeDefaultValueForType(DexFile dexFile, String type) {
+ EncodedValue subField;
+ switch (type.charAt(0)) {
+ case 'Z':
+ return BooleanEncodedValue.FalseValue;
+ case 'B':
+ return new ByteEncodedValue((byte)0);
+ case 'S':
+ return new ShortEncodedValue((short)0);
+ case 'C':
+ return new CharEncodedValue((char)0);
+ case 'I':
+ return new IntEncodedValue(0);
+ case 'J':
+ return new LongEncodedValue(0);
+ case 'F':
+ return new FloatEncodedValue(0);
+ case 'D':
+ return new DoubleEncodedValue(0);
+ case 'L':
+ case '[':
+ return NullEncodedValue.NullValue;
+ }
+ return null;
+ }
+}
diff --git a/smali/src/main/java/org/jf/smali/literalTools.java b/smali/src/main/java/org/jf/smali/literalTools.java
index 8c582722..14dc750a 100644
--- a/smali/src/main/java/org/jf/smali/literalTools.java
+++ b/smali/src/main/java/org/jf/smali/literalTools.java
@@ -1,378 +1,378 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.smali;
-
-public class literalTools
-{
- public static byte parseByte(String byteLiteral)
- throws NumberFormatException {
- if (byteLiteral == null) {
- throw new NumberFormatException("string is null");
- }
- if (byteLiteral.length() == 0) {
- throw new NumberFormatException("string is blank");
- }
-
- char[] byteChars;
- if (byteLiteral.toUpperCase().endsWith("T")) {
- byteChars = byteLiteral.substring(0, byteLiteral.length()-1).toCharArray();
- } else {
- byteChars = byteLiteral.toCharArray();
- }
-
- int position = 0;
- int radix = 10;
- boolean negative = false;
- if (byteChars[position] == '-') {
- position++;
- negative = true;
- }
-
- if (byteChars[position] == '0') {
- position++;
- if (position == byteChars.length) {
- return 0;
- } else if (byteChars[position] == 'x' || byteChars[position] == 'X') {
- radix = 16;
- position++;
- } else if (Character.digit(byteChars[position], 8) >= 0) {
- radix = 8;
- }
- }
-
- byte result = 0;
- byte shiftedResult;
- int digit;
- byte maxValue = (byte)(Byte.MAX_VALUE / (radix / 2));
-
- while (position < byteChars.length) {
- digit = Character.digit(byteChars[position], radix);
- if (digit < 0) {
- throw new NumberFormatException("The string contains invalid an digit - '" + byteChars[position] + "'");
- }
- shiftedResult = (byte)(result * radix);
- if (result > maxValue) {
- throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
- }
- if (shiftedResult < 0 && shiftedResult >= -digit) {
- throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
- }
- result = (byte)(shiftedResult + digit);
- position++;
- }
-
- if (negative) {
- //allow -0x80, which is = 0x80
- if (result == Byte.MIN_VALUE) {
- return result;
- } else if (result < 0) {
- throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
- }
- return (byte)(result * -1);
- } else {
- return result;
- }
- }
-
- public static short parseShort(String shortLiteral)
- throws NumberFormatException {
- if (shortLiteral == null) {
- throw new NumberFormatException("string is null");
- }
- if (shortLiteral.length() == 0) {
- throw new NumberFormatException("string is blank");
- }
-
- char[] shortChars;
- if (shortLiteral.toUpperCase().endsWith("S")) {
- shortChars = shortLiteral.substring(0, shortLiteral.length()-1).toCharArray();
- } else {
- shortChars = shortLiteral.toCharArray();
- }
-
- int position = 0;
- int radix = 10;
- boolean negative = false;
- if (shortChars[position] == '-') {
- position++;
- negative = true;
- }
-
- if (shortChars[position] == '0') {
- position++;
- if (position == shortChars.length) {
- return 0;
- } else if (shortChars[position] == 'x' || shortChars[position] == 'X') {
- radix = 16;
- position++;
- } else if (Character.digit(shortChars[position], 8) >= 0) {
- radix = 8;
- }
- }
-
- short result = 0;
- short shiftedResult;
- int digit;
- short maxValue = (short)(Short.MAX_VALUE / (radix / 2));
-
- while (position < shortChars.length) {
- digit = Character.digit(shortChars[position], radix);
- if (digit < 0) {
- throw new NumberFormatException("The string contains invalid an digit - '" + shortChars[position] + "'");
- }
- shiftedResult = (short)(result * radix);
- if (result > maxValue) {
- throw new NumberFormatException(shortLiteral + " cannot fit into a short");
- }
- if (shiftedResult < 0 && shiftedResult >= -digit) {
- throw new NumberFormatException(shortLiteral + " cannot fit into a short");
- }
- result = (short)(shiftedResult + digit);
- position++;
- }
-
- if (negative) {
- //allow -0x8000, which is = 0x8000
- if (result == Short.MIN_VALUE) {
- return result;
- } else if (result < 0) {
- throw new NumberFormatException(shortLiteral + " cannot fit into a short");
- }
- return (short)(result * -1);
- } else {
- return result;
- }
- }
-
- public static int parseInt(String intLiteral)
- throws NumberFormatException {
- if (intLiteral == null) {
- throw new NumberFormatException("string is null");
- }
- if (intLiteral.length() == 0) {
- throw new NumberFormatException("string is blank");
- }
-
- char[] intChars = intLiteral.toCharArray();
- int position = 0;
- int radix = 10;
- boolean negative = false;
- if (intChars[position] == '-') {
- position++;
- negative = true;
- }
-
- if (intChars[position] == '0') {
- position++;
- if (position == intChars.length) {
- return 0;
- } else if (intChars[position] == 'x' || intChars[position] == 'X') {
- radix = 16;
- position++;
- } else if (Character.digit(intChars[position], 8) >= 0) {
- radix = 8;
- }
- }
-
- int result = 0;
- int shiftedResult;
- int digit;
- int maxValue = Integer.MAX_VALUE / (radix / 2);
-
- while (position < intChars.length) {
- digit = Character.digit(intChars[position], radix);
- if (digit < 0) {
- throw new NumberFormatException("The string contains an invalid digit - '" + intChars[position] + "'");
- }
- shiftedResult = result * radix;
- if (result > maxValue) {
- throw new NumberFormatException(intLiteral + " cannot fit into an int");
- }
- if (shiftedResult < 0 && shiftedResult >= -digit) {
- throw new NumberFormatException(intLiteral + " cannot fit into an int");
- }
- result = shiftedResult + digit;
- position++;
- }
-
- if (negative) {
- //allow -0x80000000, which is = 0x80000000
- if (result == Integer.MIN_VALUE) {
- return result;
- } else if (result < 0) {
- throw new NumberFormatException(intLiteral + " cannot fit into an int");
- }
- return result * -1;
- } else {
- return result;
- }
- }
-
- public static long parseLong(String longLiteral)
- throws NumberFormatException {
- if (longLiteral == null) {
- throw new NumberFormatException("string is null");
- }
- if (longLiteral.length() == 0) {
- throw new NumberFormatException("string is blank");
- }
-
- char[] longChars;
- if (longLiteral.toUpperCase().endsWith("L")) {
- longChars = longLiteral.substring(0, longLiteral.length()-1).toCharArray();
- } else {
- longChars = longLiteral.toCharArray();
- }
-
- int position = 0;
- int radix = 10;
- boolean negative = false;
- if (longChars[position] == '-') {
- position++;
- negative = true;
- }
-
- if (longChars[position] == '0') {
- position++;
- if (position == longChars.length) {
- return 0;
- } else if (longChars[position] == 'x' || longChars[position] == 'X') {
- radix = 16;
- position++;
- } else if (Character.digit(longChars[position], 8) >= 0) {
- radix = 8;
- }
- }
-
- long result = 0;
- long shiftedResult;
- int digit;
- long maxValue = Long.MAX_VALUE / (radix / 2);
-
- while (position < longChars.length) {
- digit = Character.digit(longChars[position], radix);
- if (digit < 0) {
- throw new NumberFormatException("The string contains an invalid digit - '" + longChars[position] + "'");
- }
- shiftedResult = result * radix;
- if (result > maxValue) {
- throw new NumberFormatException(longLiteral + " cannot fit into a long");
- }
- if (shiftedResult < 0 && shiftedResult >= -digit) {
- throw new NumberFormatException(longLiteral + " cannot fit into a long");
- }
- result = shiftedResult + digit;
- position++;
- }
-
- if (negative) {
- //allow -0x8000000000000000, which is = 0x8000000000000000
- if (result == Long.MIN_VALUE) {
- return result;
- } else if (result < 0) {
- throw new NumberFormatException(longLiteral + " cannot fit into a long");
- }
- return result * -1;
- } else {
- return result;
- }
- }
-
- public static byte[] longToBytes(long value) {
- byte[] bytes = new byte[8];
-
- for (int i=0; value != 0; i++) {
- bytes[i] = (byte)value;
- value = value >>> 8;
- }
- return bytes;
- }
-
- public static byte[] intToBytes(int value) {
- byte[] bytes = new byte[4];
-
- for (int i=0; value != 0; i++) {
- bytes[i] = (byte)value;
- value = value >>> 8;
- }
- return bytes;
- }
-
- public static byte[] shortToBytes(short value) {
- byte[] bytes = new byte[2];
-
- bytes[0] = (byte)value;
- bytes[1] = (byte)(value >>> 8);
- return bytes;
- }
-
- public static byte[] floatToBytes(float value) {
- return intToBytes(Float.floatToRawIntBits(value));
- }
-
- public static byte[] doubleToBytes(double value) {
- return longToBytes(Double.doubleToRawLongBits(value));
- }
-
- public static byte[] charToBytes(char value) {
- return shortToBytes((short)value);
- }
-
- public static byte[] boolToBytes(boolean value) {
- if (value) {
- return new byte[] { 0x01 };
- } else {
- return new byte[] { 0x00 };
- }
- }
-
- public static void checkInt(long value) {
- if (value > 0xFFFFFFFF || value < -0x80000000) {
- throw new NumberFormatException(Long.toString(value) + " cannot fit into an int");
- }
- }
-
- public static void checkShort(long value) {
- if (value > 0xFFFF | value < -0x8000) {
- throw new NumberFormatException(Long.toString(value) + " cannot fit into a short");
- }
- }
-
- public static void checkByte(long value) {
- if (value > 0xFF | value < -0x80) {
- throw new NumberFormatException(Long.toString(value) + " cannot fit into a byte");
- }
- }
-
- public static void checkNibble(long value) {
- if (value > 0x0F | value < -0x08) {
- throw new NumberFormatException(Long.toString(value) + " cannot fit into a nibble");
- }
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.smali;
+
+public class literalTools
+{
+ public static byte parseByte(String byteLiteral)
+ throws NumberFormatException {
+ if (byteLiteral == null) {
+ throw new NumberFormatException("string is null");
+ }
+ if (byteLiteral.length() == 0) {
+ throw new NumberFormatException("string is blank");
+ }
+
+ char[] byteChars;
+ if (byteLiteral.toUpperCase().endsWith("T")) {
+ byteChars = byteLiteral.substring(0, byteLiteral.length()-1).toCharArray();
+ } else {
+ byteChars = byteLiteral.toCharArray();
+ }
+
+ int position = 0;
+ int radix = 10;
+ boolean negative = false;
+ if (byteChars[position] == '-') {
+ position++;
+ negative = true;
+ }
+
+ if (byteChars[position] == '0') {
+ position++;
+ if (position == byteChars.length) {
+ return 0;
+ } else if (byteChars[position] == 'x' || byteChars[position] == 'X') {
+ radix = 16;
+ position++;
+ } else if (Character.digit(byteChars[position], 8) >= 0) {
+ radix = 8;
+ }
+ }
+
+ byte result = 0;
+ byte shiftedResult;
+ int digit;
+ byte maxValue = (byte)(Byte.MAX_VALUE / (radix / 2));
+
+ while (position < byteChars.length) {
+ digit = Character.digit(byteChars[position], radix);
+ if (digit < 0) {
+ throw new NumberFormatException("The string contains invalid an digit - '" + byteChars[position] + "'");
+ }
+ shiftedResult = (byte)(result * radix);
+ if (result > maxValue) {
+ throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
+ }
+ if (shiftedResult < 0 && shiftedResult >= -digit) {
+ throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
+ }
+ result = (byte)(shiftedResult + digit);
+ position++;
+ }
+
+ if (negative) {
+ //allow -0x80, which is = 0x80
+ if (result == Byte.MIN_VALUE) {
+ return result;
+ } else if (result < 0) {
+ throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
+ }
+ return (byte)(result * -1);
+ } else {
+ return result;
+ }
+ }
+
+ public static short parseShort(String shortLiteral)
+ throws NumberFormatException {
+ if (shortLiteral == null) {
+ throw new NumberFormatException("string is null");
+ }
+ if (shortLiteral.length() == 0) {
+ throw new NumberFormatException("string is blank");
+ }
+
+ char[] shortChars;
+ if (shortLiteral.toUpperCase().endsWith("S")) {
+ shortChars = shortLiteral.substring(0, shortLiteral.length()-1).toCharArray();
+ } else {
+ shortChars = shortLiteral.toCharArray();
+ }
+
+ int position = 0;
+ int radix = 10;
+ boolean negative = false;
+ if (shortChars[position] == '-') {
+ position++;
+ negative = true;
+ }
+
+ if (shortChars[position] == '0') {
+ position++;
+ if (position == shortChars.length) {
+ return 0;
+ } else if (shortChars[position] == 'x' || shortChars[position] == 'X') {
+ radix = 16;
+ position++;
+ } else if (Character.digit(shortChars[position], 8) >= 0) {
+ radix = 8;
+ }
+ }
+
+ short result = 0;
+ short shiftedResult;
+ int digit;
+ short maxValue = (short)(Short.MAX_VALUE / (radix / 2));
+
+ while (position < shortChars.length) {
+ digit = Character.digit(shortChars[position], radix);
+ if (digit < 0) {
+ throw new NumberFormatException("The string contains invalid an digit - '" + shortChars[position] + "'");
+ }
+ shiftedResult = (short)(result * radix);
+ if (result > maxValue) {
+ throw new NumberFormatException(shortLiteral + " cannot fit into a short");
+ }
+ if (shiftedResult < 0 && shiftedResult >= -digit) {
+ throw new NumberFormatException(shortLiteral + " cannot fit into a short");
+ }
+ result = (short)(shiftedResult + digit);
+ position++;
+ }
+
+ if (negative) {
+ //allow -0x8000, which is = 0x8000
+ if (result == Short.MIN_VALUE) {
+ return result;
+ } else if (result < 0) {
+ throw new NumberFormatException(shortLiteral + " cannot fit into a short");
+ }
+ return (short)(result * -1);
+ } else {
+ return result;
+ }
+ }
+
+ public static int parseInt(String intLiteral)
+ throws NumberFormatException {
+ if (intLiteral == null) {
+ throw new NumberFormatException("string is null");
+ }
+ if (intLiteral.length() == 0) {
+ throw new NumberFormatException("string is blank");
+ }
+
+ char[] intChars = intLiteral.toCharArray();
+ int position = 0;
+ int radix = 10;
+ boolean negative = false;
+ if (intChars[position] == '-') {
+ position++;
+ negative = true;
+ }
+
+ if (intChars[position] == '0') {
+ position++;
+ if (position == intChars.length) {
+ return 0;
+ } else if (intChars[position] == 'x' || intChars[position] == 'X') {
+ radix = 16;
+ position++;
+ } else if (Character.digit(intChars[position], 8) >= 0) {
+ radix = 8;
+ }
+ }
+
+ int result = 0;
+ int shiftedResult;
+ int digit;
+ int maxValue = Integer.MAX_VALUE / (radix / 2);
+
+ while (position < intChars.length) {
+ digit = Character.digit(intChars[position], radix);
+ if (digit < 0) {
+ throw new NumberFormatException("The string contains an invalid digit - '" + intChars[position] + "'");
+ }
+ shiftedResult = result * radix;
+ if (result > maxValue) {
+ throw new NumberFormatException(intLiteral + " cannot fit into an int");
+ }
+ if (shiftedResult < 0 && shiftedResult >= -digit) {
+ throw new NumberFormatException(intLiteral + " cannot fit into an int");
+ }
+ result = shiftedResult + digit;
+ position++;
+ }
+
+ if (negative) {
+ //allow -0x80000000, which is = 0x80000000
+ if (result == Integer.MIN_VALUE) {
+ return result;
+ } else if (result < 0) {
+ throw new NumberFormatException(intLiteral + " cannot fit into an int");
+ }
+ return result * -1;
+ } else {
+ return result;
+ }
+ }
+
+ public static long parseLong(String longLiteral)
+ throws NumberFormatException {
+ if (longLiteral == null) {
+ throw new NumberFormatException("string is null");
+ }
+ if (longLiteral.length() == 0) {
+ throw new NumberFormatException("string is blank");
+ }
+
+ char[] longChars;
+ if (longLiteral.toUpperCase().endsWith("L")) {
+ longChars = longLiteral.substring(0, longLiteral.length()-1).toCharArray();
+ } else {
+ longChars = longLiteral.toCharArray();
+ }
+
+ int position = 0;
+ int radix = 10;
+ boolean negative = false;
+ if (longChars[position] == '-') {
+ position++;
+ negative = true;
+ }
+
+ if (longChars[position] == '0') {
+ position++;
+ if (position == longChars.length) {
+ return 0;
+ } else if (longChars[position] == 'x' || longChars[position] == 'X') {
+ radix = 16;
+ position++;
+ } else if (Character.digit(longChars[position], 8) >= 0) {
+ radix = 8;
+ }
+ }
+
+ long result = 0;
+ long shiftedResult;
+ int digit;
+ long maxValue = Long.MAX_VALUE / (radix / 2);
+
+ while (position < longChars.length) {
+ digit = Character.digit(longChars[position], radix);
+ if (digit < 0) {
+ throw new NumberFormatException("The string contains an invalid digit - '" + longChars[position] + "'");
+ }
+ shiftedResult = result * radix;
+ if (result > maxValue) {
+ throw new NumberFormatException(longLiteral + " cannot fit into a long");
+ }
+ if (shiftedResult < 0 && shiftedResult >= -digit) {
+ throw new NumberFormatException(longLiteral + " cannot fit into a long");
+ }
+ result = shiftedResult + digit;
+ position++;
+ }
+
+ if (negative) {
+ //allow -0x8000000000000000, which is = 0x8000000000000000
+ if (result == Long.MIN_VALUE) {
+ return result;
+ } else if (result < 0) {
+ throw new NumberFormatException(longLiteral + " cannot fit into a long");
+ }
+ return result * -1;
+ } else {
+ return result;
+ }
+ }
+
+ public static byte[] longToBytes(long value) {
+ byte[] bytes = new byte[8];
+
+ for (int i=0; value != 0; i++) {
+ bytes[i] = (byte)value;
+ value = value >>> 8;
+ }
+ return bytes;
+ }
+
+ public static byte[] intToBytes(int value) {
+ byte[] bytes = new byte[4];
+
+ for (int i=0; value != 0; i++) {
+ bytes[i] = (byte)value;
+ value = value >>> 8;
+ }
+ return bytes;
+ }
+
+ public static byte[] shortToBytes(short value) {
+ byte[] bytes = new byte[2];
+
+ bytes[0] = (byte)value;
+ bytes[1] = (byte)(value >>> 8);
+ return bytes;
+ }
+
+ public static byte[] floatToBytes(float value) {
+ return intToBytes(Float.floatToRawIntBits(value));
+ }
+
+ public static byte[] doubleToBytes(double value) {
+ return longToBytes(Double.doubleToRawLongBits(value));
+ }
+
+ public static byte[] charToBytes(char value) {
+ return shortToBytes((short)value);
+ }
+
+ public static byte[] boolToBytes(boolean value) {
+ if (value) {
+ return new byte[] { 0x01 };
+ } else {
+ return new byte[] { 0x00 };
+ }
+ }
+
+ public static void checkInt(long value) {
+ if (value > 0xFFFFFFFF || value < -0x80000000) {
+ throw new NumberFormatException(Long.toString(value) + " cannot fit into an int");
+ }
+ }
+
+ public static void checkShort(long value) {
+ if (value > 0xFFFF | value < -0x8000) {
+ throw new NumberFormatException(Long.toString(value) + " cannot fit into a short");
+ }
+ }
+
+ public static void checkByte(long value) {
+ if (value > 0xFF | value < -0x80) {
+ throw new NumberFormatException(Long.toString(value) + " cannot fit into a byte");
+ }
+ }
+
+ public static void checkNibble(long value) {
+ if (value > 0x0F | value < -0x08) {
+ throw new NumberFormatException(Long.toString(value) + " cannot fit into a nibble");
+ }
+ }
+}
diff --git a/smali/src/main/java/org/jf/smali/main.java b/smali/src/main/java/org/jf/smali/main.java
index ff96b1ed..6a429115 100644
--- a/smali/src/main/java/org/jf/smali/main.java
+++ b/smali/src/main/java/org/jf/smali/main.java
@@ -57,7 +57,7 @@ public class main {
VERSION = version;
}
-
+
/**
* This class is uninstantiable.
*/
@@ -290,7 +290,7 @@ public class main {
if (dexGen.getNumberOfSyntaxErrors() > 0) {
return false;
}
-
+
return true;
}
@@ -314,7 +314,7 @@ public class main {
System.exit(0);
}
-
+
private static void buildOptions() {
Option versionOption = OptionBuilder.withLongOpt("version")
diff --git a/smali/src/test/java/ByteLiteralTest.java b/smali/src/test/java/ByteLiteralTest.java
index 42609e30..7a07d395 100644
--- a/smali/src/test/java/ByteLiteralTest.java
+++ b/smali/src/test/java/ByteLiteralTest.java
@@ -1,139 +1,139 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.
- */
-
-import org.jf.smali.literalTools;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ByteLiteralTest
-{
-
- @Test
- public void SuccessHexTests() {
-
- Assert.assertTrue(literalTools.parseByte("0x0T") == 0x0);
- Assert.assertTrue(literalTools.parseByte("0x00") == 0x0);
- Assert.assertTrue(literalTools.parseByte("0x1T") == 0x1);
- Assert.assertTrue(literalTools.parseByte("0x12") == 0x12);
- Assert.assertTrue(literalTools.parseByte("0x7fT") == 0x7f);
- Assert.assertTrue(literalTools.parseByte("0x80t") == Byte.MIN_VALUE);
- Assert.assertTrue(literalTools.parseByte("0xFFt") == -1);
-
- Assert.assertTrue(literalTools.parseByte("-0x00") == 0);
- Assert.assertTrue(literalTools.parseByte("-0x01") == -1);
- Assert.assertTrue(literalTools.parseByte("-0x12") == -0x12);
- Assert.assertTrue(literalTools.parseByte("-0x80") == Byte.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileHexTest1() {
- literalTools.parseByte("-0x81");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest2() {
- literalTools.parseByte("-0xFF");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest3() {
- literalTools.parseByte("0x100");
- }
-
-
-
- @Test
- public void SuccessDecTests() {
- Assert.assertTrue(literalTools.parseByte("0") == 0);
- Assert.assertTrue(literalTools.parseByte("1t") == 1);
- Assert.assertTrue(literalTools.parseByte("123") == 123);
- Assert.assertTrue(literalTools.parseByte("127T") == 127);
- Assert.assertTrue(literalTools.parseByte("128") == Byte.MIN_VALUE);
- Assert.assertTrue(literalTools.parseByte("255") == -1);
-
-
- Assert.assertTrue(literalTools.parseByte("-0") == 0);
- Assert.assertTrue(literalTools.parseByte("-1") == -1);
- Assert.assertTrue(literalTools.parseByte("-123") == -123);
- Assert.assertTrue(literalTools.parseByte("-127") == -127);
- Assert.assertTrue(literalTools.parseByte("-128") == Byte.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileDecTest1() {
- literalTools.parseByte("-129");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest2() {
- literalTools.parseByte("-255");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest3() {
- literalTools.parseByte("256");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest4() {
- literalTools.parseByte("260");
- }
-
-
- @Test
- public void SuccessOctTests() {
- Assert.assertTrue(literalTools.parseByte("00") == 00);
- Assert.assertTrue(literalTools.parseByte("01") == 01);
- Assert.assertTrue(literalTools.parseByte("0123t") == 0123);
- Assert.assertTrue(literalTools.parseByte("0177") == Byte.MAX_VALUE);
- Assert.assertTrue(literalTools.parseByte("0200T") == Byte.MIN_VALUE);
- Assert.assertTrue(literalTools.parseByte("0377") == -1);
-
-
- Assert.assertTrue(literalTools.parseByte("-00") == 0);
- Assert.assertTrue(literalTools.parseByte("-01") == -1);
- Assert.assertTrue(literalTools.parseByte("-0123") == -0123);
- Assert.assertTrue(literalTools.parseByte("-0177") == -0177);
- Assert.assertTrue(literalTools.parseByte("-0200") == Byte.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileOctTest1() {
- literalTools.parseByte("-0201");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest2() {
- literalTools.parseByte("-0377");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest3() {
- literalTools.parseByte("0400");
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.
+ */
+
+import org.jf.smali.literalTools;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ByteLiteralTest
+{
+
+ @Test
+ public void SuccessHexTests() {
+
+ Assert.assertTrue(literalTools.parseByte("0x0T") == 0x0);
+ Assert.assertTrue(literalTools.parseByte("0x00") == 0x0);
+ Assert.assertTrue(literalTools.parseByte("0x1T") == 0x1);
+ Assert.assertTrue(literalTools.parseByte("0x12") == 0x12);
+ Assert.assertTrue(literalTools.parseByte("0x7fT") == 0x7f);
+ Assert.assertTrue(literalTools.parseByte("0x80t") == Byte.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseByte("0xFFt") == -1);
+
+ Assert.assertTrue(literalTools.parseByte("-0x00") == 0);
+ Assert.assertTrue(literalTools.parseByte("-0x01") == -1);
+ Assert.assertTrue(literalTools.parseByte("-0x12") == -0x12);
+ Assert.assertTrue(literalTools.parseByte("-0x80") == Byte.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileHexTest1() {
+ literalTools.parseByte("-0x81");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest2() {
+ literalTools.parseByte("-0xFF");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest3() {
+ literalTools.parseByte("0x100");
+ }
+
+
+
+ @Test
+ public void SuccessDecTests() {
+ Assert.assertTrue(literalTools.parseByte("0") == 0);
+ Assert.assertTrue(literalTools.parseByte("1t") == 1);
+ Assert.assertTrue(literalTools.parseByte("123") == 123);
+ Assert.assertTrue(literalTools.parseByte("127T") == 127);
+ Assert.assertTrue(literalTools.parseByte("128") == Byte.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseByte("255") == -1);
+
+
+ Assert.assertTrue(literalTools.parseByte("-0") == 0);
+ Assert.assertTrue(literalTools.parseByte("-1") == -1);
+ Assert.assertTrue(literalTools.parseByte("-123") == -123);
+ Assert.assertTrue(literalTools.parseByte("-127") == -127);
+ Assert.assertTrue(literalTools.parseByte("-128") == Byte.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileDecTest1() {
+ literalTools.parseByte("-129");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest2() {
+ literalTools.parseByte("-255");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest3() {
+ literalTools.parseByte("256");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest4() {
+ literalTools.parseByte("260");
+ }
+
+
+ @Test
+ public void SuccessOctTests() {
+ Assert.assertTrue(literalTools.parseByte("00") == 00);
+ Assert.assertTrue(literalTools.parseByte("01") == 01);
+ Assert.assertTrue(literalTools.parseByte("0123t") == 0123);
+ Assert.assertTrue(literalTools.parseByte("0177") == Byte.MAX_VALUE);
+ Assert.assertTrue(literalTools.parseByte("0200T") == Byte.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseByte("0377") == -1);
+
+
+ Assert.assertTrue(literalTools.parseByte("-00") == 0);
+ Assert.assertTrue(literalTools.parseByte("-01") == -1);
+ Assert.assertTrue(literalTools.parseByte("-0123") == -0123);
+ Assert.assertTrue(literalTools.parseByte("-0177") == -0177);
+ Assert.assertTrue(literalTools.parseByte("-0200") == Byte.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileOctTest1() {
+ literalTools.parseByte("-0201");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest2() {
+ literalTools.parseByte("-0377");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest3() {
+ literalTools.parseByte("0400");
+ }
+}
diff --git a/smali/src/test/java/IntLiteralTest.java b/smali/src/test/java/IntLiteralTest.java
index eb7dbc8d..15258252 100644
--- a/smali/src/test/java/IntLiteralTest.java
+++ b/smali/src/test/java/IntLiteralTest.java
@@ -1,144 +1,144 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.
- */
-
-import org.jf.smali.literalTools;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class IntLiteralTest
-{
-
- @Test
- public void SuccessHexTests() {
-
- Assert.assertTrue(literalTools.parseInt("0x0") == 0x0);
- Assert.assertTrue(literalTools.parseInt("0x00") == 0x0);
- Assert.assertTrue(literalTools.parseInt("0x1") == 0x1);
- Assert.assertTrue(literalTools.parseInt("0x12345678") == 0x12345678);
- Assert.assertTrue(literalTools.parseInt("0x7fffffff") == 0x7fffffff);
- Assert.assertTrue(literalTools.parseInt("0x80000000") == Integer.MIN_VALUE);
- Assert.assertTrue(literalTools.parseInt("0xFFFFFFFF") == -1);
-
- Assert.assertTrue(literalTools.parseInt("-0x00") == 0);
- Assert.assertTrue(literalTools.parseInt("-0x01") == -1);
- Assert.assertTrue(literalTools.parseInt("-0x12345678") == -0x12345678);
- Assert.assertTrue(literalTools.parseInt("-0x80000000") == Integer.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileHexTest1() {
- literalTools.parseInt("-0x80000001");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest2() {
- literalTools.parseInt("-0xFFFFFFFF");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest3() {
- literalTools.parseInt("0x100000000");
- }
-
-
-
- @Test
- public void SuccessDecTests() {
- Assert.assertTrue(literalTools.parseInt("0") == 0);
- Assert.assertTrue(literalTools.parseInt("1") == 1);
- Assert.assertTrue(literalTools.parseInt("1234567890") == 1234567890);
- Assert.assertTrue(literalTools.parseInt("2147483647") == 2147483647);
- Assert.assertTrue(literalTools.parseInt("2147483648") == Integer.MIN_VALUE);
- Assert.assertTrue(literalTools.parseInt("4294967295") == -1);
-
-
- Assert.assertTrue(literalTools.parseInt("-0") == 0);
- Assert.assertTrue(literalTools.parseInt("-1") == -1);
- Assert.assertTrue(literalTools.parseInt("-1234567890") == -1234567890);
- Assert.assertTrue(literalTools.parseInt("-2147483647") == -2147483647);
- Assert.assertTrue(literalTools.parseInt("-2147483648") == Integer.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileDecTest1() {
- literalTools.parseInt("-2147483649");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest2() {
- literalTools.parseInt("-4294967295");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest3() {
- literalTools.parseInt("4294967296");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest4() {
- literalTools.parseInt("4294967300");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest5() {
- literalTools.parseInt("8589934592");
- }
-
-
- @Test
- public void SuccessOctTests() {
- Assert.assertTrue(literalTools.parseInt("00") == 00);
- Assert.assertTrue(literalTools.parseInt("01") == 01);
- Assert.assertTrue(literalTools.parseInt("012345670123") == 012345670123);
- Assert.assertTrue(literalTools.parseInt("017777777777") == Integer.MAX_VALUE);
- Assert.assertTrue(literalTools.parseInt("020000000000") == Integer.MIN_VALUE);
- Assert.assertTrue(literalTools.parseInt("037777777777") == -1);
-
-
- Assert.assertTrue(literalTools.parseInt("-00") == 0);
- Assert.assertTrue(literalTools.parseInt("-01") == -1);
- Assert.assertTrue(literalTools.parseInt("-012345670123") == -012345670123);
- Assert.assertTrue(literalTools.parseInt("-017777777777") == -017777777777);
- Assert.assertTrue(literalTools.parseInt("-020000000000") == Integer.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileOctTest1() {
- literalTools.parseInt("-020000000001");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest2() {
- literalTools.parseInt("-037777777777");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest3() {
- literalTools.parseInt("040000000000");
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.
+ */
+
+import org.jf.smali.literalTools;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class IntLiteralTest
+{
+
+ @Test
+ public void SuccessHexTests() {
+
+ Assert.assertTrue(literalTools.parseInt("0x0") == 0x0);
+ Assert.assertTrue(literalTools.parseInt("0x00") == 0x0);
+ Assert.assertTrue(literalTools.parseInt("0x1") == 0x1);
+ Assert.assertTrue(literalTools.parseInt("0x12345678") == 0x12345678);
+ Assert.assertTrue(literalTools.parseInt("0x7fffffff") == 0x7fffffff);
+ Assert.assertTrue(literalTools.parseInt("0x80000000") == Integer.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseInt("0xFFFFFFFF") == -1);
+
+ Assert.assertTrue(literalTools.parseInt("-0x00") == 0);
+ Assert.assertTrue(literalTools.parseInt("-0x01") == -1);
+ Assert.assertTrue(literalTools.parseInt("-0x12345678") == -0x12345678);
+ Assert.assertTrue(literalTools.parseInt("-0x80000000") == Integer.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileHexTest1() {
+ literalTools.parseInt("-0x80000001");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest2() {
+ literalTools.parseInt("-0xFFFFFFFF");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest3() {
+ literalTools.parseInt("0x100000000");
+ }
+
+
+
+ @Test
+ public void SuccessDecTests() {
+ Assert.assertTrue(literalTools.parseInt("0") == 0);
+ Assert.assertTrue(literalTools.parseInt("1") == 1);
+ Assert.assertTrue(literalTools.parseInt("1234567890") == 1234567890);
+ Assert.assertTrue(literalTools.parseInt("2147483647") == 2147483647);
+ Assert.assertTrue(literalTools.parseInt("2147483648") == Integer.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseInt("4294967295") == -1);
+
+
+ Assert.assertTrue(literalTools.parseInt("-0") == 0);
+ Assert.assertTrue(literalTools.parseInt("-1") == -1);
+ Assert.assertTrue(literalTools.parseInt("-1234567890") == -1234567890);
+ Assert.assertTrue(literalTools.parseInt("-2147483647") == -2147483647);
+ Assert.assertTrue(literalTools.parseInt("-2147483648") == Integer.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileDecTest1() {
+ literalTools.parseInt("-2147483649");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest2() {
+ literalTools.parseInt("-4294967295");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest3() {
+ literalTools.parseInt("4294967296");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest4() {
+ literalTools.parseInt("4294967300");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest5() {
+ literalTools.parseInt("8589934592");
+ }
+
+
+ @Test
+ public void SuccessOctTests() {
+ Assert.assertTrue(literalTools.parseInt("00") == 00);
+ Assert.assertTrue(literalTools.parseInt("01") == 01);
+ Assert.assertTrue(literalTools.parseInt("012345670123") == 012345670123);
+ Assert.assertTrue(literalTools.parseInt("017777777777") == Integer.MAX_VALUE);
+ Assert.assertTrue(literalTools.parseInt("020000000000") == Integer.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseInt("037777777777") == -1);
+
+
+ Assert.assertTrue(literalTools.parseInt("-00") == 0);
+ Assert.assertTrue(literalTools.parseInt("-01") == -1);
+ Assert.assertTrue(literalTools.parseInt("-012345670123") == -012345670123);
+ Assert.assertTrue(literalTools.parseInt("-017777777777") == -017777777777);
+ Assert.assertTrue(literalTools.parseInt("-020000000000") == Integer.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileOctTest1() {
+ literalTools.parseInt("-020000000001");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest2() {
+ literalTools.parseInt("-037777777777");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest3() {
+ literalTools.parseInt("040000000000");
+ }
+}
diff --git a/smali/src/test/java/LongLiteralTest.java b/smali/src/test/java/LongLiteralTest.java
index cf749de7..f54ef8f6 100644
--- a/smali/src/test/java/LongLiteralTest.java
+++ b/smali/src/test/java/LongLiteralTest.java
@@ -1,139 +1,139 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.
- */
-
-import org.jf.smali.literalTools;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class LongLiteralTest
-{
-
- @Test
- public void SuccessHexTests() {
-
- Assert.assertTrue(literalTools.parseLong("0x0L") == 0x0);
- Assert.assertTrue(literalTools.parseLong("0x00") == 0x0);
- Assert.assertTrue(literalTools.parseLong("0x1L") == 0x1);
- Assert.assertTrue(literalTools.parseLong("0x1234567890123456L") == 0x1234567890123456L);
- Assert.assertTrue(literalTools.parseLong("0x7fffffffffffffffL") == 0x7fffffffffffffffL);
- Assert.assertTrue(literalTools.parseLong("0x8000000000000000L") == Long.MIN_VALUE);
- Assert.assertTrue(literalTools.parseLong("0xFFFFFFFFFFFFFFFFL") == -1);
-
- Assert.assertTrue(literalTools.parseLong("-0x00L") == 0);
- Assert.assertTrue(literalTools.parseLong("-0x01L") == -1);
- Assert.assertTrue(literalTools.parseLong("-0x1234567890123456L") == -0x1234567890123456L);
- Assert.assertTrue(literalTools.parseLong("-0x8000000000000000") == Long.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileHexTest1() {
- literalTools.parseLong("-0x8000000000000001");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest2() {
- literalTools.parseLong("-0xFFFFFFFFFFFFFFFF");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest3() {
- literalTools.parseLong("0x10000000000000000");
- }
-
-
-
- @Test
- public void SuccessDecTests() {
- Assert.assertTrue(literalTools.parseLong("0L") == 0);
- Assert.assertTrue(literalTools.parseLong("1") == 1);
- Assert.assertTrue(literalTools.parseLong("1234567890123456789") == 1234567890123456789L);
- Assert.assertTrue(literalTools.parseLong("9223372036854775807") == 9223372036854775807L);
- Assert.assertTrue(literalTools.parseLong("9223372036854775808") == Long.MIN_VALUE);
- Assert.assertTrue(literalTools.parseLong("18446744073709551615L") == -1);
-
-
- Assert.assertTrue(literalTools.parseLong("-0") == 0);
- Assert.assertTrue(literalTools.parseLong("-1") == -1);
- Assert.assertTrue(literalTools.parseLong("-1234567890123456789") == -1234567890123456789L);
- Assert.assertTrue(literalTools.parseLong("-9223372036854775807") == -9223372036854775807L);
- Assert.assertTrue(literalTools.parseLong("-9223372036854775808") == Long.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileDecTest1() {
- literalTools.parseLong("-9223372036854775809");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest2() {
- literalTools.parseLong("-18446744073709551616");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest3() {
- literalTools.parseLong("18446744073709551617");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest4() {
- literalTools.parseLong("18446744073709551700");
- }
-
-
- @Test
- public void SuccessOctTests() {
- Assert.assertTrue(literalTools.parseLong("00") == 00);
- Assert.assertTrue(literalTools.parseLong("01") == 01);
- Assert.assertTrue(literalTools.parseLong("0123456701234567012345") == 0123456701234567012345L);
- Assert.assertTrue(literalTools.parseLong("0777777777777777777777") == Long.MAX_VALUE);
- Assert.assertTrue(literalTools.parseLong("01000000000000000000000") == Long.MIN_VALUE);
- Assert.assertTrue(literalTools.parseLong("01777777777777777777777") == -1);
-
-
- Assert.assertTrue(literalTools.parseLong("-00") == 0);
- Assert.assertTrue(literalTools.parseLong("-01") == -1);
- Assert.assertTrue(literalTools.parseLong("-0123456701234567012345") == -0123456701234567012345L);
- Assert.assertTrue(literalTools.parseLong("-0777777777777777777777") == -0777777777777777777777L);
- Assert.assertTrue(literalTools.parseLong("-01000000000000000000000") == Long.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileOctTest1() {
- literalTools.parseLong("-01000000000000000000001");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest2() {
- literalTools.parseLong("-01777777777777777777777");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest3() {
- literalTools.parseLong("02000000000000000000000");
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.
+ */
+
+import org.jf.smali.literalTools;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LongLiteralTest
+{
+
+ @Test
+ public void SuccessHexTests() {
+
+ Assert.assertTrue(literalTools.parseLong("0x0L") == 0x0);
+ Assert.assertTrue(literalTools.parseLong("0x00") == 0x0);
+ Assert.assertTrue(literalTools.parseLong("0x1L") == 0x1);
+ Assert.assertTrue(literalTools.parseLong("0x1234567890123456L") == 0x1234567890123456L);
+ Assert.assertTrue(literalTools.parseLong("0x7fffffffffffffffL") == 0x7fffffffffffffffL);
+ Assert.assertTrue(literalTools.parseLong("0x8000000000000000L") == Long.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseLong("0xFFFFFFFFFFFFFFFFL") == -1);
+
+ Assert.assertTrue(literalTools.parseLong("-0x00L") == 0);
+ Assert.assertTrue(literalTools.parseLong("-0x01L") == -1);
+ Assert.assertTrue(literalTools.parseLong("-0x1234567890123456L") == -0x1234567890123456L);
+ Assert.assertTrue(literalTools.parseLong("-0x8000000000000000") == Long.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileHexTest1() {
+ literalTools.parseLong("-0x8000000000000001");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest2() {
+ literalTools.parseLong("-0xFFFFFFFFFFFFFFFF");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest3() {
+ literalTools.parseLong("0x10000000000000000");
+ }
+
+
+
+ @Test
+ public void SuccessDecTests() {
+ Assert.assertTrue(literalTools.parseLong("0L") == 0);
+ Assert.assertTrue(literalTools.parseLong("1") == 1);
+ Assert.assertTrue(literalTools.parseLong("1234567890123456789") == 1234567890123456789L);
+ Assert.assertTrue(literalTools.parseLong("9223372036854775807") == 9223372036854775807L);
+ Assert.assertTrue(literalTools.parseLong("9223372036854775808") == Long.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseLong("18446744073709551615L") == -1);
+
+
+ Assert.assertTrue(literalTools.parseLong("-0") == 0);
+ Assert.assertTrue(literalTools.parseLong("-1") == -1);
+ Assert.assertTrue(literalTools.parseLong("-1234567890123456789") == -1234567890123456789L);
+ Assert.assertTrue(literalTools.parseLong("-9223372036854775807") == -9223372036854775807L);
+ Assert.assertTrue(literalTools.parseLong("-9223372036854775808") == Long.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileDecTest1() {
+ literalTools.parseLong("-9223372036854775809");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest2() {
+ literalTools.parseLong("-18446744073709551616");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest3() {
+ literalTools.parseLong("18446744073709551617");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest4() {
+ literalTools.parseLong("18446744073709551700");
+ }
+
+
+ @Test
+ public void SuccessOctTests() {
+ Assert.assertTrue(literalTools.parseLong("00") == 00);
+ Assert.assertTrue(literalTools.parseLong("01") == 01);
+ Assert.assertTrue(literalTools.parseLong("0123456701234567012345") == 0123456701234567012345L);
+ Assert.assertTrue(literalTools.parseLong("0777777777777777777777") == Long.MAX_VALUE);
+ Assert.assertTrue(literalTools.parseLong("01000000000000000000000") == Long.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseLong("01777777777777777777777") == -1);
+
+
+ Assert.assertTrue(literalTools.parseLong("-00") == 0);
+ Assert.assertTrue(literalTools.parseLong("-01") == -1);
+ Assert.assertTrue(literalTools.parseLong("-0123456701234567012345") == -0123456701234567012345L);
+ Assert.assertTrue(literalTools.parseLong("-0777777777777777777777") == -0777777777777777777777L);
+ Assert.assertTrue(literalTools.parseLong("-01000000000000000000000") == Long.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileOctTest1() {
+ literalTools.parseLong("-01000000000000000000001");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest2() {
+ literalTools.parseLong("-01777777777777777777777");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest3() {
+ literalTools.parseLong("02000000000000000000000");
+ }
+}
diff --git a/smali/src/test/java/ShortLiteralTest.java b/smali/src/test/java/ShortLiteralTest.java
index 16d1553e..2b9824fb 100644
--- a/smali/src/test/java/ShortLiteralTest.java
+++ b/smali/src/test/java/ShortLiteralTest.java
@@ -1,139 +1,139 @@
-/*
- * [The "BSD licence"]
- * Copyright (c) 2009 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.
- */
-
-import org.jf.smali.literalTools;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ShortLiteralTest
-{
-
- @Test
- public void SuccessHexTests() {
-
- Assert.assertTrue(literalTools.parseShort("0x0") == 0x0);
- Assert.assertTrue(literalTools.parseShort("0x00") == 0x0);
- Assert.assertTrue(literalTools.parseShort("0x1") == 0x1);
- Assert.assertTrue(literalTools.parseShort("0x1234") == 0x1234);
- Assert.assertTrue(literalTools.parseShort("0x7fff") == 0x7fff);
- Assert.assertTrue(literalTools.parseShort("0x8000") == Short.MIN_VALUE);
- Assert.assertTrue(literalTools.parseShort("0xFFFF") == -1);
-
- Assert.assertTrue(literalTools.parseShort("-0x00") == 0);
- Assert.assertTrue(literalTools.parseShort("-0x01") == -1);
- Assert.assertTrue(literalTools.parseShort("-0x1234") == -0x1234);
- Assert.assertTrue(literalTools.parseShort("-0x8000") == Short.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileHexTest1() {
- literalTools.parseShort("-0x8001");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest2() {
- literalTools.parseShort("-0xFFFF");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailHexTest3() {
- literalTools.parseShort("0x100000");
- }
-
-
-
- @Test
- public void SuccessDecTests() {
- Assert.assertTrue(literalTools.parseShort("0") == 0);
- Assert.assertTrue(literalTools.parseShort("1") == 1);
- Assert.assertTrue(literalTools.parseShort("12345") == 12345);
- Assert.assertTrue(literalTools.parseShort("32767") == 32767);
- Assert.assertTrue(literalTools.parseShort("32768") == Short.MIN_VALUE);
- Assert.assertTrue(literalTools.parseShort("65535") == -1);
-
-
- Assert.assertTrue(literalTools.parseShort("-0") == 0);
- Assert.assertTrue(literalTools.parseShort("-1") == -1);
- Assert.assertTrue(literalTools.parseShort("-12345") == -12345);
- Assert.assertTrue(literalTools.parseShort("-32767") == -32767);
- Assert.assertTrue(literalTools.parseShort("-32768") == Short.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileDecTest1() {
- literalTools.parseShort("-32769");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest2() {
- literalTools.parseShort("-65535");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest3() {
- literalTools.parseShort("65536");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailDecTest4() {
- literalTools.parseShort("65600");
- }
-
-
- @Test
- public void SuccessOctTests() {
- Assert.assertTrue(literalTools.parseShort("00") == 00);
- Assert.assertTrue(literalTools.parseShort("01") == 01);
- Assert.assertTrue(literalTools.parseShort("012345") == 012345);
- Assert.assertTrue(literalTools.parseShort("077777") == Short.MAX_VALUE);
- Assert.assertTrue(literalTools.parseShort("0100000") == Short.MIN_VALUE);
- Assert.assertTrue(literalTools.parseShort("0177777") == -1);
-
-
- Assert.assertTrue(literalTools.parseShort("-00") == 0);
- Assert.assertTrue(literalTools.parseShort("-01") == -1);
- Assert.assertTrue(literalTools.parseShort("-012345") == -012345);
- Assert.assertTrue(literalTools.parseShort("-077777") == -077777);
- Assert.assertTrue(literalTools.parseShort("-0100000") == Short.MIN_VALUE);
- }
-
- @Test(expected=NumberFormatException.class)
- public void FaileOctTest1() {
- literalTools.parseShort("-0100001");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest2() {
- literalTools.parseShort("-0177777");
- }
-
- @Test(expected=NumberFormatException.class)
- public void FailOctTest3() {
- literalTools.parseShort("0200000");
- }
-}
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2009 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.
+ */
+
+import org.jf.smali.literalTools;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ShortLiteralTest
+{
+
+ @Test
+ public void SuccessHexTests() {
+
+ Assert.assertTrue(literalTools.parseShort("0x0") == 0x0);
+ Assert.assertTrue(literalTools.parseShort("0x00") == 0x0);
+ Assert.assertTrue(literalTools.parseShort("0x1") == 0x1);
+ Assert.assertTrue(literalTools.parseShort("0x1234") == 0x1234);
+ Assert.assertTrue(literalTools.parseShort("0x7fff") == 0x7fff);
+ Assert.assertTrue(literalTools.parseShort("0x8000") == Short.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseShort("0xFFFF") == -1);
+
+ Assert.assertTrue(literalTools.parseShort("-0x00") == 0);
+ Assert.assertTrue(literalTools.parseShort("-0x01") == -1);
+ Assert.assertTrue(literalTools.parseShort("-0x1234") == -0x1234);
+ Assert.assertTrue(literalTools.parseShort("-0x8000") == Short.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileHexTest1() {
+ literalTools.parseShort("-0x8001");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest2() {
+ literalTools.parseShort("-0xFFFF");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailHexTest3() {
+ literalTools.parseShort("0x100000");
+ }
+
+
+
+ @Test
+ public void SuccessDecTests() {
+ Assert.assertTrue(literalTools.parseShort("0") == 0);
+ Assert.assertTrue(literalTools.parseShort("1") == 1);
+ Assert.assertTrue(literalTools.parseShort("12345") == 12345);
+ Assert.assertTrue(literalTools.parseShort("32767") == 32767);
+ Assert.assertTrue(literalTools.parseShort("32768") == Short.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseShort("65535") == -1);
+
+
+ Assert.assertTrue(literalTools.parseShort("-0") == 0);
+ Assert.assertTrue(literalTools.parseShort("-1") == -1);
+ Assert.assertTrue(literalTools.parseShort("-12345") == -12345);
+ Assert.assertTrue(literalTools.parseShort("-32767") == -32767);
+ Assert.assertTrue(literalTools.parseShort("-32768") == Short.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileDecTest1() {
+ literalTools.parseShort("-32769");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest2() {
+ literalTools.parseShort("-65535");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest3() {
+ literalTools.parseShort("65536");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailDecTest4() {
+ literalTools.parseShort("65600");
+ }
+
+
+ @Test
+ public void SuccessOctTests() {
+ Assert.assertTrue(literalTools.parseShort("00") == 00);
+ Assert.assertTrue(literalTools.parseShort("01") == 01);
+ Assert.assertTrue(literalTools.parseShort("012345") == 012345);
+ Assert.assertTrue(literalTools.parseShort("077777") == Short.MAX_VALUE);
+ Assert.assertTrue(literalTools.parseShort("0100000") == Short.MIN_VALUE);
+ Assert.assertTrue(literalTools.parseShort("0177777") == -1);
+
+
+ Assert.assertTrue(literalTools.parseShort("-00") == 0);
+ Assert.assertTrue(literalTools.parseShort("-01") == -1);
+ Assert.assertTrue(literalTools.parseShort("-012345") == -012345);
+ Assert.assertTrue(literalTools.parseShort("-077777") == -077777);
+ Assert.assertTrue(literalTools.parseShort("-0100000") == Short.MIN_VALUE);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FaileOctTest1() {
+ literalTools.parseShort("-0100001");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest2() {
+ literalTools.parseShort("-0177777");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void FailOctTest3() {
+ literalTools.parseShort("0200000");
+ }
+}