mirror of
https://github.com/revanced/smali.git
synced 2025-05-28 11:50:12 +02:00
line ending and trailing whitespace cleanup
git-svn-id: https://smali.googlecode.com/svn/trunk@500 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
eb78b7fa64
commit
5867263eb5
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>();
|
||||
|
||||
for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
|
||||
|
@ -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),
|
||||
|
@ -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))};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()) {
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;-><init>()V
|
||||
aput-object v0, v1, v4
|
||||
|
@ -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; i<clazz->ifieldCount; 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; i<count; i++) {
|
||||
const InlineOperation *inlineOp = &inlineTable[i];
|
||||
|
||||
|
||||
ClassObject *clazz = dvmFindSystemClassNoInit(inlineOp->classDescriptor);
|
||||
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;
|
||||
|
@ -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<AnnotationDirectoryItem> {
|
||||
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 <code>AnnotationDirectoryItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationDirectoryItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationDirectoryItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classAnnotations The annotations associated with the overall class
|
||||
* @param fieldAnnotationFields An array of <code>FieldIdItem</code> objects that the annotations in
|
||||
* <code>fieldAnnotations</code> are associated with
|
||||
* @param fieldAnnotations An array of <code>AnnotationSetItem</code> objects that contain the annotations for the
|
||||
* fields in <code>fieldAnnotationFields</code>
|
||||
* @param methodAnnotationMethods An array of <code>MethodIdItem</code> objects that the annotations in
|
||||
* <code>methodAnnotations</code> are associated with
|
||||
* @param methodAnnotations An array of <code>AnnotationSetItem</code> objects that contain the annotations for the
|
||||
* methods in <code>methodAnnotationMethods</code>
|
||||
* @param parameterAnnotationMethods An array of <code>MethodIdItem</code> objects that the annotations in
|
||||
* <code>parameterAnnotations</code> are associated with
|
||||
* @param parameterAnnotations An array of <code>AnnotationSetRefList</code> objects that contain the parameter
|
||||
* annotations for the methods in <code>parameterAnnotationMethods</code>
|
||||
*/
|
||||
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 <code>AnnotationDirectoryItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classAnnotations The annotations associated with the class
|
||||
* @param fieldAnnotations A list of <code>FieldAnnotation</code> objects containing the field annotations
|
||||
* @param methodAnnotations A list of <code>MethodAnnotation</code> objects containing the method annotations
|
||||
* @param parameterAnnotations A list of <code>ParameterAnnotation</code> objects containin the parameter
|
||||
* annotations
|
||||
* @return an <code>AnnotationItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
*/
|
||||
public static AnnotationDirectoryItem getInternedAnnotationDirectoryItem(DexFile dexFile,
|
||||
AnnotationSetItem classAnnotations,
|
||||
List<FieldAnnotation> fieldAnnotations,
|
||||
List<MethodAnnotation> methodAnnotations,
|
||||
List<ParameterAnnotation> 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; i<fieldAnnotations.length; i++) {
|
||||
fieldAnnotationFields[i] = dexFile.FieldIdsSection.getItemByIndex(in.readInt());
|
||||
fieldAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
methodAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
|
||||
methodAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
parameterAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
|
||||
parameterAnnotations[i] = (AnnotationSetRefList)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_REF_LIST, in.readInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 16 + (
|
||||
(fieldAnnotations==null?0:fieldAnnotations.length) +
|
||||
(methodAnnotations==null?0:methodAnnotations.length) +
|
||||
(parameterAnnotations==null?0:parameterAnnotations.length)) * 8;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
if (!isInternable() && parent != null) {
|
||||
out.annotate(0, parent.getClassType().getTypeDescriptor());
|
||||
}
|
||||
if (classAnnotations != null) {
|
||||
out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset()));
|
||||
} else {
|
||||
out.annotate(4, "class_annotations_off:");
|
||||
}
|
||||
|
||||
int length = fieldAnnotations==null?0:fieldAnnotations.length;
|
||||
out.annotate(4, "annotated_fields_size: 0x" + Integer.toHexString(length) + " (" +
|
||||
length + ")");
|
||||
length = methodAnnotations==null?0:methodAnnotations.length;
|
||||
out.annotate(4, "annotated_methods_size: 0x" + Integer.toHexString(length) + " (" +
|
||||
length + ")");
|
||||
length = parameterAnnotations==null?0:parameterAnnotations.length;
|
||||
out.annotate(4, "annotated_parameters_size: 0x" + Integer.toHexString(length) + " (" +
|
||||
length + ")");
|
||||
|
||||
int index;
|
||||
if (fieldAnnotations != null) {
|
||||
index = 0;
|
||||
for (int i=0; i<fieldAnnotations.length; i++) {
|
||||
out.annotate(0, "[" + index++ + "] field_annotation");
|
||||
|
||||
out.indent();
|
||||
out.annotate(4, "field: " + fieldAnnotationFields[i].getFieldName().getStringValue() + ":" +
|
||||
fieldAnnotationFields[i].getFieldType().getTypeDescriptor());
|
||||
out.annotate(4, "annotations_off: 0x" + Integer.toHexString(fieldAnnotations[i].getOffset()));
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
|
||||
if (methodAnnotations != null) {
|
||||
index = 0;
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
out.annotate(0, "[" + index++ + "] method_annotation");
|
||||
out.indent();
|
||||
out.annotate(4, "method: " + methodAnnotationMethods[i].getMethodString());
|
||||
out.annotate(4, "annotations_off: 0x" + Integer.toHexString(methodAnnotations[i].getOffset()));
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterAnnotations != null) {
|
||||
index = 0;
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
out.annotate(0, "[" + index++ + "] parameter_annotation");
|
||||
out.indent();
|
||||
out.annotate(4, "method: " + parameterAnnotationMethods[i].getMethodString());
|
||||
out.annotate(4, "annotations_off: 0x" + Integer.toHexString(parameterAnnotations[i].getOffset()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.writeInt(classAnnotations==null?0:classAnnotations.getOffset());
|
||||
out.writeInt(fieldAnnotations==null?0:fieldAnnotations.length);
|
||||
out.writeInt(methodAnnotations==null?0:methodAnnotations.length);
|
||||
out.writeInt(parameterAnnotations==null?0:parameterAnnotations.length);
|
||||
|
||||
if (fieldAnnotations != null) {
|
||||
for (int i=0; i<fieldAnnotations.length; i++) {
|
||||
out.writeInt(fieldAnnotationFields[i].getIndex());
|
||||
out.writeInt(fieldAnnotations[i].getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
if (methodAnnotations != null) {
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
out.writeInt(methodAnnotationMethods[i].getIndex());
|
||||
out.writeInt(methodAnnotations[i].getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterAnnotations != null) {
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
out.writeInt(parameterAnnotationMethods[i].getIndex());
|
||||
out.writeInt(parameterAnnotations[i].getOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationDirectoryItem o) {
|
||||
if (!isInternable()) {
|
||||
if (!o.isInternable()) {
|
||||
return parent.compareTo(o.parent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!o.isInternable()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return classAnnotations.compareTo(o.classAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The annotations associated with the class
|
||||
*/
|
||||
public AnnotationSetItem getClassAnnotations() {
|
||||
return classAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the field annotations, calling delegate.processFieldAnnotations for each
|
||||
* @param delegate the delegate to call
|
||||
*/
|
||||
public void iterateFieldAnnotations(FieldAnnotationIteratorDelegate delegate) {
|
||||
for (int i=0; i<fieldAnnotationFields.length; i++) {
|
||||
delegate.processFieldAnnotations(fieldAnnotationFields[i], fieldAnnotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface FieldAnnotationIteratorDelegate {
|
||||
void processFieldAnnotations(FieldIdItem field, AnnotationSetItem fieldAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of field annotations in this <code>AnnotationDirectoryItem</code>
|
||||
*/
|
||||
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; i<methodAnnotationMethods.length; i++) {
|
||||
delegate.processMethodAnnotations(methodAnnotationMethods[i], methodAnnotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface MethodAnnotationIteratorDelegate {
|
||||
void processMethodAnnotations(MethodIdItem method, AnnotationSetItem methodAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of method annotations in this <code>AnnotationDirectoryItem</code>
|
||||
*/
|
||||
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; i<parameterAnnotationMethods.length; i++) {
|
||||
delegate.processParameterAnnotations(parameterAnnotationMethods[i], parameterAnnotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ParameterAnnotationIteratorDelegate {
|
||||
void processParameterAnnotations(MethodIdItem method, AnnotationSetRefList parameterAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of parameter annotations in this <code>AnnotationDirectoryItem</code>
|
||||
*/
|
||||
public int getParameterAnnotationCount() {
|
||||
return parameterAnnotationMethods.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this <code>AnnotationDirectoryItem</code> 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 <code>ClassDefItem</code> that this <code>AnnotationDirectoryItem</code> is associated with.
|
||||
* This is only applicable if this AnnotationDirectoryItem contains only class annotations, and no field, method
|
||||
* or parameter annotations.
|
||||
* @param classDefItem the <code>ClassDefItem</code> that this <code>AnnotationDirectoryItem</code> 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<FieldAnnotation> {
|
||||
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<MethodAnnotation> {
|
||||
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<ParameterAnnotation> {
|
||||
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<AnnotationDirectoryItem> {
|
||||
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 <code>AnnotationDirectoryItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationDirectoryItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationDirectoryItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classAnnotations The annotations associated with the overall class
|
||||
* @param fieldAnnotationFields An array of <code>FieldIdItem</code> objects that the annotations in
|
||||
* <code>fieldAnnotations</code> are associated with
|
||||
* @param fieldAnnotations An array of <code>AnnotationSetItem</code> objects that contain the annotations for the
|
||||
* fields in <code>fieldAnnotationFields</code>
|
||||
* @param methodAnnotationMethods An array of <code>MethodIdItem</code> objects that the annotations in
|
||||
* <code>methodAnnotations</code> are associated with
|
||||
* @param methodAnnotations An array of <code>AnnotationSetItem</code> objects that contain the annotations for the
|
||||
* methods in <code>methodAnnotationMethods</code>
|
||||
* @param parameterAnnotationMethods An array of <code>MethodIdItem</code> objects that the annotations in
|
||||
* <code>parameterAnnotations</code> are associated with
|
||||
* @param parameterAnnotations An array of <code>AnnotationSetRefList</code> objects that contain the parameter
|
||||
* annotations for the methods in <code>parameterAnnotationMethods</code>
|
||||
*/
|
||||
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 <code>AnnotationDirectoryItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classAnnotations The annotations associated with the class
|
||||
* @param fieldAnnotations A list of <code>FieldAnnotation</code> objects containing the field annotations
|
||||
* @param methodAnnotations A list of <code>MethodAnnotation</code> objects containing the method annotations
|
||||
* @param parameterAnnotations A list of <code>ParameterAnnotation</code> objects containin the parameter
|
||||
* annotations
|
||||
* @return an <code>AnnotationItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
*/
|
||||
public static AnnotationDirectoryItem getInternedAnnotationDirectoryItem(DexFile dexFile,
|
||||
AnnotationSetItem classAnnotations,
|
||||
List<FieldAnnotation> fieldAnnotations,
|
||||
List<MethodAnnotation> methodAnnotations,
|
||||
List<ParameterAnnotation> 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; i<fieldAnnotations.length; i++) {
|
||||
fieldAnnotationFields[i] = dexFile.FieldIdsSection.getItemByIndex(in.readInt());
|
||||
fieldAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
methodAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
|
||||
methodAnnotations[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
parameterAnnotationMethods[i] = dexFile.MethodIdsSection.getItemByIndex(in.readInt());
|
||||
parameterAnnotations[i] = (AnnotationSetRefList)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_REF_LIST, in.readInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 16 + (
|
||||
(fieldAnnotations==null?0:fieldAnnotations.length) +
|
||||
(methodAnnotations==null?0:methodAnnotations.length) +
|
||||
(parameterAnnotations==null?0:parameterAnnotations.length)) * 8;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
if (!isInternable() && parent != null) {
|
||||
out.annotate(0, parent.getClassType().getTypeDescriptor());
|
||||
}
|
||||
if (classAnnotations != null) {
|
||||
out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset()));
|
||||
} else {
|
||||
out.annotate(4, "class_annotations_off:");
|
||||
}
|
||||
|
||||
int length = fieldAnnotations==null?0:fieldAnnotations.length;
|
||||
out.annotate(4, "annotated_fields_size: 0x" + Integer.toHexString(length) + " (" +
|
||||
length + ")");
|
||||
length = methodAnnotations==null?0:methodAnnotations.length;
|
||||
out.annotate(4, "annotated_methods_size: 0x" + Integer.toHexString(length) + " (" +
|
||||
length + ")");
|
||||
length = parameterAnnotations==null?0:parameterAnnotations.length;
|
||||
out.annotate(4, "annotated_parameters_size: 0x" + Integer.toHexString(length) + " (" +
|
||||
length + ")");
|
||||
|
||||
int index;
|
||||
if (fieldAnnotations != null) {
|
||||
index = 0;
|
||||
for (int i=0; i<fieldAnnotations.length; i++) {
|
||||
out.annotate(0, "[" + index++ + "] field_annotation");
|
||||
|
||||
out.indent();
|
||||
out.annotate(4, "field: " + fieldAnnotationFields[i].getFieldName().getStringValue() + ":" +
|
||||
fieldAnnotationFields[i].getFieldType().getTypeDescriptor());
|
||||
out.annotate(4, "annotations_off: 0x" + Integer.toHexString(fieldAnnotations[i].getOffset()));
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
|
||||
if (methodAnnotations != null) {
|
||||
index = 0;
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
out.annotate(0, "[" + index++ + "] method_annotation");
|
||||
out.indent();
|
||||
out.annotate(4, "method: " + methodAnnotationMethods[i].getMethodString());
|
||||
out.annotate(4, "annotations_off: 0x" + Integer.toHexString(methodAnnotations[i].getOffset()));
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterAnnotations != null) {
|
||||
index = 0;
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
out.annotate(0, "[" + index++ + "] parameter_annotation");
|
||||
out.indent();
|
||||
out.annotate(4, "method: " + parameterAnnotationMethods[i].getMethodString());
|
||||
out.annotate(4, "annotations_off: 0x" + Integer.toHexString(parameterAnnotations[i].getOffset()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.writeInt(classAnnotations==null?0:classAnnotations.getOffset());
|
||||
out.writeInt(fieldAnnotations==null?0:fieldAnnotations.length);
|
||||
out.writeInt(methodAnnotations==null?0:methodAnnotations.length);
|
||||
out.writeInt(parameterAnnotations==null?0:parameterAnnotations.length);
|
||||
|
||||
if (fieldAnnotations != null) {
|
||||
for (int i=0; i<fieldAnnotations.length; i++) {
|
||||
out.writeInt(fieldAnnotationFields[i].getIndex());
|
||||
out.writeInt(fieldAnnotations[i].getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
if (methodAnnotations != null) {
|
||||
for (int i=0; i<methodAnnotations.length; i++) {
|
||||
out.writeInt(methodAnnotationMethods[i].getIndex());
|
||||
out.writeInt(methodAnnotations[i].getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterAnnotations != null) {
|
||||
for (int i=0; i<parameterAnnotations.length; i++) {
|
||||
out.writeInt(parameterAnnotationMethods[i].getIndex());
|
||||
out.writeInt(parameterAnnotations[i].getOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationDirectoryItem o) {
|
||||
if (!isInternable()) {
|
||||
if (!o.isInternable()) {
|
||||
return parent.compareTo(o.parent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!o.isInternable()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return classAnnotations.compareTo(o.classAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The annotations associated with the class
|
||||
*/
|
||||
public AnnotationSetItem getClassAnnotations() {
|
||||
return classAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the field annotations, calling delegate.processFieldAnnotations for each
|
||||
* @param delegate the delegate to call
|
||||
*/
|
||||
public void iterateFieldAnnotations(FieldAnnotationIteratorDelegate delegate) {
|
||||
for (int i=0; i<fieldAnnotationFields.length; i++) {
|
||||
delegate.processFieldAnnotations(fieldAnnotationFields[i], fieldAnnotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface FieldAnnotationIteratorDelegate {
|
||||
void processFieldAnnotations(FieldIdItem field, AnnotationSetItem fieldAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of field annotations in this <code>AnnotationDirectoryItem</code>
|
||||
*/
|
||||
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; i<methodAnnotationMethods.length; i++) {
|
||||
delegate.processMethodAnnotations(methodAnnotationMethods[i], methodAnnotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface MethodAnnotationIteratorDelegate {
|
||||
void processMethodAnnotations(MethodIdItem method, AnnotationSetItem methodAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of method annotations in this <code>AnnotationDirectoryItem</code>
|
||||
*/
|
||||
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; i<parameterAnnotationMethods.length; i++) {
|
||||
delegate.processParameterAnnotations(parameterAnnotationMethods[i], parameterAnnotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ParameterAnnotationIteratorDelegate {
|
||||
void processParameterAnnotations(MethodIdItem method, AnnotationSetRefList parameterAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of parameter annotations in this <code>AnnotationDirectoryItem</code>
|
||||
*/
|
||||
public int getParameterAnnotationCount() {
|
||||
return parameterAnnotationMethods.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this <code>AnnotationDirectoryItem</code> 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 <code>ClassDefItem</code> that this <code>AnnotationDirectoryItem</code> is associated with.
|
||||
* This is only applicable if this AnnotationDirectoryItem contains only class annotations, and no field, method
|
||||
* or parameter annotations.
|
||||
* @param classDefItem the <code>ClassDefItem</code> that this <code>AnnotationDirectoryItem</code> 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<FieldAnnotation> {
|
||||
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<MethodAnnotation> {
|
||||
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<ParameterAnnotation> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<AnnotationItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private AnnotationVisibility visibility;
|
||||
private AnnotationEncodedSubValue annotationValue;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>AnnotationItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param visibility The visibility of this annotation
|
||||
* @param annotationValue The value of this annotation
|
||||
*/
|
||||
private AnnotationItem(DexFile dexFile, AnnotationVisibility visibility,
|
||||
AnnotationEncodedSubValue annotationValue) {
|
||||
super(dexFile);
|
||||
this.visibility = visibility;
|
||||
this.annotationValue = annotationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>AnnotationItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param visibility The visibility of this annotation
|
||||
* @param annotationValue The value of this annotation
|
||||
* @return an <code>AnnotationItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
*/
|
||||
public static AnnotationItem 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<AnnotationItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private AnnotationVisibility visibility;
|
||||
private AnnotationEncodedSubValue annotationValue;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>AnnotationItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param visibility The visibility of this annotation
|
||||
* @param annotationValue The value of this annotation
|
||||
*/
|
||||
private AnnotationItem(DexFile dexFile, AnnotationVisibility visibility,
|
||||
AnnotationEncodedSubValue annotationValue) {
|
||||
super(dexFile);
|
||||
this.visibility = visibility;
|
||||
this.annotationValue = annotationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>AnnotationItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param visibility The visibility of this annotation
|
||||
* @param annotationValue The value of this annotation
|
||||
* @return an <code>AnnotationItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
*/
|
||||
public static AnnotationItem 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<AnnotationSetItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private AnnotationItem[] annotations;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>AnnotationSetItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationSetItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationSetItem</code> for the given annotations
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotations The annotations for this <code>AnnotationSetItem</code>
|
||||
*/
|
||||
private AnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) {
|
||||
super(dexFile);
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>AnnotationSetItem</code> for the given annotations, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotations The annotations for this <code>AnnotationSetItem</code>
|
||||
* @return an <code>AnnotationSetItem</code> for the given annotations
|
||||
*/
|
||||
public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, List<AnnotationItem> 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; i<annotations.length; i++) {
|
||||
annotations[i] = (AnnotationItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_ITEM,
|
||||
in.readInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 4 + annotations.length * 4;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "size: 0x" + Integer.toHexString(annotations.length) + " (" + annotations.length + ")");
|
||||
for (AnnotationItem annotationItem: annotations) {
|
||||
out.annotate(4, "annotation_off: 0x" + Integer.toHexString(annotationItem.getOffset()) + " - " +
|
||||
annotationItem.getEncodedAnnotation().annotationType.getTypeDescriptor());
|
||||
}
|
||||
}
|
||||
out.writeInt(annotations.length);
|
||||
for (AnnotationItem annotationItem: annotations) {
|
||||
out.writeInt(annotationItem.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATION_SET_ITEM;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationSetItem o) {
|
||||
if (o == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int comp = annotations.length - o.annotations.length;
|
||||
if (comp == 0) {
|
||||
for (int i=0; i<annotations.length; i++) {
|
||||
comp = annotations[i].compareTo(o.annotations[i]);
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An array of the <code>AnnotationItem</code> objects in this <code>AnnotationSetItem</code>
|
||||
*/
|
||||
public AnnotationItem[] getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate and cache the hashcode
|
||||
*/
|
||||
private void calcHashCode() {
|
||||
hashCode = 0;
|
||||
for (AnnotationItem annotationItem: annotations) {
|
||||
hashCode = hashCode * 31 + annotationItem.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
//there's a small possibility that the actual hash code will be 0. If so, we'll
|
||||
//just end up recalculating it each time
|
||||
if (hashCode == 0)
|
||||
calcHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this==o) {
|
||||
return true;
|
||||
}
|
||||
if (o==null || !this.getClass().equals(o.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnnotationSetItem other = (AnnotationSetItem)o;
|
||||
return (this.compareTo(other) == 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* [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<AnnotationSetItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private AnnotationItem[] annotations;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>AnnotationSetItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationSetItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationSetItem</code> for the given annotations
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotations The annotations for this <code>AnnotationSetItem</code>
|
||||
*/
|
||||
private AnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) {
|
||||
super(dexFile);
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>AnnotationSetItem</code> for the given annotations, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotations The annotations for this <code>AnnotationSetItem</code>
|
||||
* @return an <code>AnnotationSetItem</code> for the given annotations
|
||||
*/
|
||||
public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, List<AnnotationItem> 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; i<annotations.length; i++) {
|
||||
annotations[i] = (AnnotationItem)readContext.getOffsettedItemByOffset(ItemType.TYPE_ANNOTATION_ITEM,
|
||||
in.readInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 4 + annotations.length * 4;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "size: 0x" + Integer.toHexString(annotations.length) + " (" + annotations.length + ")");
|
||||
for (AnnotationItem annotationItem: annotations) {
|
||||
out.annotate(4, "annotation_off: 0x" + Integer.toHexString(annotationItem.getOffset()) + " - " +
|
||||
annotationItem.getEncodedAnnotation().annotationType.getTypeDescriptor());
|
||||
}
|
||||
}
|
||||
out.writeInt(annotations.length);
|
||||
for (AnnotationItem annotationItem: annotations) {
|
||||
out.writeInt(annotationItem.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATION_SET_ITEM;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationSetItem o) {
|
||||
if (o == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int comp = annotations.length - o.annotations.length;
|
||||
if (comp == 0) {
|
||||
for (int i=0; i<annotations.length; i++) {
|
||||
comp = annotations[i].compareTo(o.annotations[i]);
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An array of the <code>AnnotationItem</code> objects in this <code>AnnotationSetItem</code>
|
||||
*/
|
||||
public AnnotationItem[] getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate and cache the hashcode
|
||||
*/
|
||||
private void calcHashCode() {
|
||||
hashCode = 0;
|
||||
for (AnnotationItem annotationItem: annotations) {
|
||||
hashCode = hashCode * 31 + annotationItem.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
//there's a small possibility that the actual hash code will be 0. If so, we'll
|
||||
//just end up recalculating it each time
|
||||
if (hashCode == 0)
|
||||
calcHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this==o) {
|
||||
return true;
|
||||
}
|
||||
if (o==null || !this.getClass().equals(o.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnnotationSetItem other = (AnnotationSetItem)o;
|
||||
return (this.compareTo(other) == 0);
|
||||
}
|
||||
}
|
||||
|
@ -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<AnnotationSetRefList> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private AnnotationSetItem[] annotationSets;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>AnnotationSetRefList</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationSetRefList(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationSetRefList</code> for the given annotation sets
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotationSets The annotationSets for this <code>AnnotationSetRefList</code>
|
||||
*/
|
||||
private AnnotationSetRefList(DexFile dexFile, AnnotationSetItem[] annotationSets) {
|
||||
super(dexFile);
|
||||
this.annotationSets = annotationSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>AnnotationSetRefList</code> for the given annotation sets, and that has been interned into the
|
||||
* given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotationSets The annotation sets for this <code>AnnotationSetRefList</code>
|
||||
* @return an <code>AnnotationSetItem</code> for the given annotations
|
||||
*/
|
||||
public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile,
|
||||
List<AnnotationSetItem> annotationSets) {
|
||||
AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()];
|
||||
annotationSets.toArray(annotationSetsArray);
|
||||
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray);
|
||||
return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void readItem(Input in, ReadContext readContext) {
|
||||
annotationSets = new AnnotationSetItem[in.readInt()];
|
||||
|
||||
for (int i=0; i<annotationSets.length; i++) {
|
||||
annotationSets[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 4 + annotationSets.length * 4;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length +
|
||||
")");
|
||||
for (AnnotationSetItem annotationSetItem: annotationSets) {
|
||||
out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset()));
|
||||
}
|
||||
}
|
||||
out.writeInt(annotationSets.length);
|
||||
for (AnnotationSetItem annotationSetItem: annotationSets) {
|
||||
out.writeInt(annotationSetItem.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATION_SET_REF_LIST;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationSetRefList o) {
|
||||
int comp = annotationSets.length - o.annotationSets.length;
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
|
||||
for (int i=0; i<annotationSets.length; i++) {
|
||||
comp = annotationSets[i].compareTo(o.annotationSets[i]);
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An array of the <code>AnnotationSetItem</code> objects that make up this
|
||||
* <code>AnnotationSetRefList</code>
|
||||
*/
|
||||
public AnnotationSetItem[] getAnnotationSets() {
|
||||
return annotationSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate and cache the hashcode
|
||||
*/
|
||||
private void calcHashCode() {
|
||||
hashCode = 0;
|
||||
for (AnnotationSetItem annotationSetItem: annotationSets) {
|
||||
hashCode = hashCode * 31 + annotationSetItem.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
//there's a small possibility that the actual hash code will be 0. If so, we'll
|
||||
//just end up recalculating it each time
|
||||
if (hashCode == 0)
|
||||
calcHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this==o) {
|
||||
return true;
|
||||
}
|
||||
if (o==null || !this.getClass().equals(o.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnnotationSetRefList other = (AnnotationSetRefList)o;
|
||||
return (this.compareTo(other) == 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* [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<AnnotationSetRefList> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private AnnotationSetItem[] annotationSets;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>AnnotationSetRefList</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected AnnotationSetRefList(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AnnotationSetRefList</code> for the given annotation sets
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotationSets The annotationSets for this <code>AnnotationSetRefList</code>
|
||||
*/
|
||||
private AnnotationSetRefList(DexFile dexFile, AnnotationSetItem[] annotationSets) {
|
||||
super(dexFile);
|
||||
this.annotationSets = annotationSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>AnnotationSetRefList</code> for the given annotation sets, and that has been interned into the
|
||||
* given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param annotationSets The annotation sets for this <code>AnnotationSetRefList</code>
|
||||
* @return an <code>AnnotationSetItem</code> for the given annotations
|
||||
*/
|
||||
public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile,
|
||||
List<AnnotationSetItem> annotationSets) {
|
||||
AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()];
|
||||
annotationSets.toArray(annotationSetsArray);
|
||||
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray);
|
||||
return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void readItem(Input in, ReadContext readContext) {
|
||||
annotationSets = new AnnotationSetItem[in.readInt()];
|
||||
|
||||
for (int i=0; i<annotationSets.length; i++) {
|
||||
annotationSets[i] = (AnnotationSetItem)readContext.getOffsettedItemByOffset(
|
||||
ItemType.TYPE_ANNOTATION_SET_ITEM, in.readInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 4 + annotationSets.length * 4;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "size: 0x" + Integer.toHexString(annotationSets.length) + " (" + annotationSets.length +
|
||||
")");
|
||||
for (AnnotationSetItem annotationSetItem: annotationSets) {
|
||||
out.annotate(4, "annotation_set_off: 0x" + Integer.toHexString(annotationSetItem.getOffset()));
|
||||
}
|
||||
}
|
||||
out.writeInt(annotationSets.length);
|
||||
for (AnnotationSetItem annotationSetItem: annotationSets) {
|
||||
out.writeInt(annotationSetItem.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_ANNOTATION_SET_REF_LIST;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(AnnotationSetRefList o) {
|
||||
int comp = annotationSets.length - o.annotationSets.length;
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
|
||||
for (int i=0; i<annotationSets.length; i++) {
|
||||
comp = annotationSets[i].compareTo(o.annotationSets[i]);
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An array of the <code>AnnotationSetItem</code> objects that make up this
|
||||
* <code>AnnotationSetRefList</code>
|
||||
*/
|
||||
public AnnotationSetItem[] getAnnotationSets() {
|
||||
return annotationSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate and cache the hashcode
|
||||
*/
|
||||
private void calcHashCode() {
|
||||
hashCode = 0;
|
||||
for (AnnotationSetItem annotationSetItem: annotationSets) {
|
||||
hashCode = hashCode * 31 + annotationSetItem.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
//there's a small possibility that the actual hash code will be 0. If so, we'll
|
||||
//just end up recalculating it each time
|
||||
if (hashCode == 0)
|
||||
calcHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this==o) {
|
||||
return true;
|
||||
}
|
||||
if (o==null || !this.getClass().equals(o.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnnotationSetRefList other = (AnnotationSetRefList)o;
|
||||
return (this.compareTo(other) == 0);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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<ClassDefItem> {
|
||||
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 <code>ClassDefItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected ClassDefItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ClassDefItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType The type of this class
|
||||
* @param accessFlags The access flags of this class
|
||||
* @param superType The superclass of this class, or null if none (only valid for java.lang.Object)
|
||||
* @param implementedInterfaces A list of the interfaces that this class implements, or null if none
|
||||
* @param sourceFile The main source file that this class is defined in, or null if not available
|
||||
* @param annotations The annotations for this class and its fields, methods and method parameters, or null if none
|
||||
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class
|
||||
* @param staticFieldInitializers The initial values for this class's static fields, or null if none. The initial
|
||||
* values should be in the same order as the static fields in the <code>ClassDataItem</code>. It can contain
|
||||
* fewer items than static fields, in which case the remaining static fields will be initialized with a default
|
||||
* value of null/0. The initial value for any fields that don't specifically have a value can be either the
|
||||
* type-appropriate null/0 encoded value, or null.
|
||||
*/
|
||||
private ClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags, 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 <code>ClassDefItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType The type of this class
|
||||
* @param accessFlags The access flags of this class
|
||||
* @param superType The superclass of this class, or null if none (only valid for java.lang.Object)
|
||||
* @param implementedInterfaces A list of the interfaces that this class implements, or null if none
|
||||
* @param sourceFile The main source file that this class is defined in, or null if not available
|
||||
* @param annotations The annotations for this class and its fields, methods and method parameters, or null if none
|
||||
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class
|
||||
* @param staticFieldInitializers The initial values for this class's static fields, or null if none. If it is not
|
||||
* null, it must contain the same number of items as the number of static fields in this class. The value in the
|
||||
* <code>StaticFieldInitializer</code> for any field that doesn't have an explicit initial value can either be null
|
||||
* or be the type-appropriate null/0 value.
|
||||
* @return a <code>ClassDefItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
*/
|
||||
public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags,
|
||||
TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile,
|
||||
AnnotationDirectoryItem annotations, ClassDataItem classData,
|
||||
List<StaticFieldInitializer> 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<ClassDefItem> section, int offset) {
|
||||
ClassDefPlacer cdp = new ClassDefPlacer(section);
|
||||
return cdp.placeSection(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class places the items within a ClassDefItem section, such that superclasses and interfaces are
|
||||
* placed before sub/implementing classes
|
||||
*/
|
||||
private static class ClassDefPlacer {
|
||||
private final IndexedSection<ClassDefItem> section;
|
||||
private final HashMap<TypeIdItem, ClassDefItem> unplacedClassDefsByType =
|
||||
new HashMap<TypeIdItem, ClassDefItem>();
|
||||
|
||||
private int currentIndex = 0;
|
||||
private int currentOffset;
|
||||
|
||||
public ClassDefPlacer(IndexedSection<ClassDefItem> section) {
|
||||
this.section = section;
|
||||
|
||||
for (ClassDefItem classDefItem: section.items) {
|
||||
TypeIdItem typeIdItem = classDefItem.classType;
|
||||
unplacedClassDefsByType.put(typeIdItem, classDefItem);
|
||||
}
|
||||
}
|
||||
|
||||
public int placeSection(int offset) {
|
||||
currentOffset = offset;
|
||||
|
||||
if (section.DexFile.getSortAllItems()) {
|
||||
//presort the list, to guarantee a unique ordering
|
||||
Collections.sort(section.items, new Comparator<ClassDefItem>() {
|
||||
public int compare(ClassDefItem a, ClassDefItem b) {
|
||||
return a.getClassType().compareTo(b.getClassType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//we need to initialize the offset for all the classes to -1, so we can tell which ones
|
||||
//have been placed
|
||||
for (ClassDefItem classDefItem: section.items) {
|
||||
classDefItem.offset = -1;
|
||||
}
|
||||
|
||||
for (ClassDefItem classDefItem: section.items) {
|
||||
placeClass(classDefItem);
|
||||
}
|
||||
|
||||
for (ClassDefItem classDefItem: unplacedClassDefsByType.values()) {
|
||||
section.items.set(classDefItem.getIndex(), classDefItem);
|
||||
}
|
||||
|
||||
return currentOffset;
|
||||
}
|
||||
|
||||
private void placeClass(ClassDefItem classDefItem) {
|
||||
if (classDefItem.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<StaticFieldInitializer> {
|
||||
public final EncodedValue value;
|
||||
public final ClassDataItem.EncodedField field;
|
||||
public StaticFieldInitializer(EncodedValue value, ClassDataItem.EncodedField field) {
|
||||
this.value = value;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public int compareTo(StaticFieldInitializer other) {
|
||||
return field.compareTo(other.field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A helper method to sort the static field initializers and populate the default values as needed
|
||||
* @param dexFile the <code>DexFile</code>
|
||||
* @param staticFieldInitializers the initial values
|
||||
* @return an interned EncodedArrayItem containing the static field initializers
|
||||
*/
|
||||
private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
|
||||
List<StaticFieldInitializer> 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<ClassDefItem> {
|
||||
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 <code>ClassDefItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected ClassDefItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ClassDefItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType The type of this class
|
||||
* @param accessFlags The access flags of this class
|
||||
* @param superType The superclass of this class, or null if none (only valid for java.lang.Object)
|
||||
* @param implementedInterfaces A list of the interfaces that this class implements, or null if none
|
||||
* @param sourceFile The main source file that this class is defined in, or null if not available
|
||||
* @param annotations The annotations for this class and its fields, methods and method parameters, or null if none
|
||||
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class
|
||||
* @param staticFieldInitializers The initial values for this class's static fields, or null if none. The initial
|
||||
* values should be in the same order as the static fields in the <code>ClassDataItem</code>. It can contain
|
||||
* fewer items than static fields, in which case the remaining static fields will be initialized with a default
|
||||
* value of null/0. The initial value for any fields that don't specifically have a value can be either the
|
||||
* type-appropriate null/0 encoded value, or null.
|
||||
*/
|
||||
private ClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags, 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 <code>ClassDefItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType The type of this class
|
||||
* @param accessFlags The access flags of this class
|
||||
* @param superType The superclass of this class, or null if none (only valid for java.lang.Object)
|
||||
* @param implementedInterfaces A list of the interfaces that this class implements, or null if none
|
||||
* @param sourceFile The main source file that this class is defined in, or null if not available
|
||||
* @param annotations The annotations for this class and its fields, methods and method parameters, or null if none
|
||||
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class
|
||||
* @param staticFieldInitializers The initial values for this class's static fields, or null if none. If it is not
|
||||
* null, it must contain the same number of items as the number of static fields in this class. The value in the
|
||||
* <code>StaticFieldInitializer</code> for any field that doesn't have an explicit initial value can either be null
|
||||
* or be the type-appropriate null/0 value.
|
||||
* @return a <code>ClassDefItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
*/
|
||||
public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags,
|
||||
TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile,
|
||||
AnnotationDirectoryItem annotations, ClassDataItem classData,
|
||||
List<StaticFieldInitializer> 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<ClassDefItem> section, int offset) {
|
||||
ClassDefPlacer cdp = new ClassDefPlacer(section);
|
||||
return cdp.placeSection(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class places the items within a ClassDefItem section, such that superclasses and interfaces are
|
||||
* placed before sub/implementing classes
|
||||
*/
|
||||
private static class ClassDefPlacer {
|
||||
private final IndexedSection<ClassDefItem> section;
|
||||
private final HashMap<TypeIdItem, ClassDefItem> unplacedClassDefsByType =
|
||||
new HashMap<TypeIdItem, ClassDefItem>();
|
||||
|
||||
private int currentIndex = 0;
|
||||
private int currentOffset;
|
||||
|
||||
public ClassDefPlacer(IndexedSection<ClassDefItem> section) {
|
||||
this.section = section;
|
||||
|
||||
for (ClassDefItem classDefItem: section.items) {
|
||||
TypeIdItem typeIdItem = classDefItem.classType;
|
||||
unplacedClassDefsByType.put(typeIdItem, classDefItem);
|
||||
}
|
||||
}
|
||||
|
||||
public int placeSection(int offset) {
|
||||
currentOffset = offset;
|
||||
|
||||
if (section.DexFile.getSortAllItems()) {
|
||||
//presort the list, to guarantee a unique ordering
|
||||
Collections.sort(section.items, new Comparator<ClassDefItem>() {
|
||||
public int compare(ClassDefItem a, ClassDefItem b) {
|
||||
return a.getClassType().compareTo(b.getClassType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//we need to initialize the offset for all the classes to -1, so we can tell which ones
|
||||
//have been placed
|
||||
for (ClassDefItem classDefItem: section.items) {
|
||||
classDefItem.offset = -1;
|
||||
}
|
||||
|
||||
for (ClassDefItem classDefItem: section.items) {
|
||||
placeClass(classDefItem);
|
||||
}
|
||||
|
||||
for (ClassDefItem classDefItem: unplacedClassDefsByType.values()) {
|
||||
section.items.set(classDefItem.getIndex(), classDefItem);
|
||||
}
|
||||
|
||||
return currentOffset;
|
||||
}
|
||||
|
||||
private void placeClass(ClassDefItem classDefItem) {
|
||||
if (classDefItem.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<StaticFieldInitializer> {
|
||||
public final EncodedValue value;
|
||||
public final ClassDataItem.EncodedField field;
|
||||
public StaticFieldInitializer(EncodedValue value, ClassDataItem.EncodedField field) {
|
||||
this.value = value;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public int compareTo(StaticFieldInitializer other) {
|
||||
return field.compareTo(other.field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A helper method to sort the static field initializers and populate the default values as needed
|
||||
* @param dexFile the <code>DexFile</code>
|
||||
* @param staticFieldInitializers the initial values
|
||||
* @return an interned EncodedArrayItem containing the static field initializers
|
||||
*/
|
||||
private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
|
||||
List<StaticFieldInitializer> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<ArrayElement> getElements() {
|
||||
return new Iterator<ArrayElement>() {
|
||||
final int elementCount = getElementCount();
|
||||
int i=0;
|
||||
int position = bufferIndex + 8;
|
||||
final ArrayElement arrayElement = new ArrayElement(buffer, getElementWidth());
|
||||
|
||||
public boolean hasNext() {
|
||||
return i<elementCount;
|
||||
}
|
||||
|
||||
public ArrayElement next() {
|
||||
arrayElement.bufferIndex = position;
|
||||
position += arrayElement.elementWidth;
|
||||
i++;
|
||||
return arrayElement;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for an ArrayDataPseudoInstruction must by NOP");
|
||||
}
|
||||
return new ArrayDataPseudoInstruction(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.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<ArrayElement> getElements() {
|
||||
return new Iterator<ArrayElement>() {
|
||||
final int elementCount = getElementCount();
|
||||
int i=0;
|
||||
int position = bufferIndex + 8;
|
||||
final ArrayElement arrayElement = new ArrayElement(buffer, getElementWidth());
|
||||
|
||||
public boolean hasNext() {
|
||||
return i<elementCount;
|
||||
}
|
||||
|
||||
public ArrayElement next() {
|
||||
arrayElement.bufferIndex = position;
|
||||
position += arrayElement.elementWidth;
|
||||
i++;
|
||||
return arrayElement;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for an ArrayDataPseudoInstruction must by NOP");
|
||||
}
|
||||
return new ArrayDataPseudoInstruction(buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.Code.Format;
|
||||
|
||||
import org.jf.dexlib.Code.Instruction;
|
||||
|
||||
public enum Format {
|
||||
Format10t(Instruction10t.Factory, 2),
|
||||
Format10x(Instruction10x.Factory, 2),
|
||||
Format11n(Instruction11n.Factory, 2),
|
||||
Format11x(Instruction11x.Factory, 2),
|
||||
Format12x(Instruction12x.Factory, 2),
|
||||
Format20t(Instruction20t.Factory, 4),
|
||||
Format21c(Instruction21c.Factory, 4),
|
||||
Format21h(Instruction21h.Factory, 4),
|
||||
Format21s(Instruction21s.Factory, 4),
|
||||
Format21t(Instruction21t.Factory, 4),
|
||||
Format22b(Instruction22b.Factory, 4),
|
||||
Format22c(Instruction22c.Factory, 4),
|
||||
Format22cs(Instruction22cs.Factory, 4),
|
||||
Format22csf(null, 4),
|
||||
Format22s(Instruction22s.Factory, 4),
|
||||
Format22t(Instruction22t.Factory, 4),
|
||||
Format22x(Instruction22x.Factory, 4),
|
||||
Format23x(Instruction23x.Factory, 4),
|
||||
Format30t(Instruction30t.Factory, 6),
|
||||
Format31c(Instruction31c.Factory, 6),
|
||||
Format31i(Instruction31i.Factory, 6),
|
||||
Format31t(Instruction31t.Factory, 6),
|
||||
Format32x(Instruction32x.Factory, 6),
|
||||
Format35c(Instruction35c.Factory, 6),
|
||||
Format35s(Instruction35s.Factory, 6),
|
||||
Format35sf(null, 6),
|
||||
Format35ms(Instruction35ms.Factory, 6),
|
||||
Format35msf(null, 6),
|
||||
Format3rc(Instruction3rc.Factory, 6),
|
||||
Format3rms(Instruction3rms.Factory, 6),
|
||||
Format3rmsf(null, 6),
|
||||
Format51l(Instruction51l.Factory, 10),
|
||||
ArrayData(null, -1, true),
|
||||
PackedSwitchData(null, -1, true),
|
||||
SparseSwitchData(null, -1, true),
|
||||
UnresolvedNullReference(null, -1, false),
|
||||
DeadInstruction(null, -1, false)
|
||||
;
|
||||
|
||||
public final Instruction.InstructionFactory Factory;
|
||||
public final int size;
|
||||
public final boolean variableSizeFormat;
|
||||
|
||||
private Format(Instruction.InstructionFactory factory, int size) {
|
||||
this(factory, size, false);
|
||||
}
|
||||
|
||||
private Format(Instruction.InstructionFactory factory, int size, boolean variableSizeFormat) {
|
||||
this.Factory = factory;
|
||||
this.size = size;
|
||||
this.variableSizeFormat = variableSizeFormat;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* [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;
|
||||
|
||||
public enum Format {
|
||||
Format10t(Instruction10t.Factory, 2),
|
||||
Format10x(Instruction10x.Factory, 2),
|
||||
Format11n(Instruction11n.Factory, 2),
|
||||
Format11x(Instruction11x.Factory, 2),
|
||||
Format12x(Instruction12x.Factory, 2),
|
||||
Format20t(Instruction20t.Factory, 4),
|
||||
Format21c(Instruction21c.Factory, 4),
|
||||
Format21h(Instruction21h.Factory, 4),
|
||||
Format21s(Instruction21s.Factory, 4),
|
||||
Format21t(Instruction21t.Factory, 4),
|
||||
Format22b(Instruction22b.Factory, 4),
|
||||
Format22c(Instruction22c.Factory, 4),
|
||||
Format22cs(Instruction22cs.Factory, 4),
|
||||
Format22csf(null, 4),
|
||||
Format22s(Instruction22s.Factory, 4),
|
||||
Format22t(Instruction22t.Factory, 4),
|
||||
Format22x(Instruction22x.Factory, 4),
|
||||
Format23x(Instruction23x.Factory, 4),
|
||||
Format30t(Instruction30t.Factory, 6),
|
||||
Format31c(Instruction31c.Factory, 6),
|
||||
Format31i(Instruction31i.Factory, 6),
|
||||
Format31t(Instruction31t.Factory, 6),
|
||||
Format32x(Instruction32x.Factory, 6),
|
||||
Format35c(Instruction35c.Factory, 6),
|
||||
Format35s(Instruction35s.Factory, 6),
|
||||
Format35sf(null, 6),
|
||||
Format35ms(Instruction35ms.Factory, 6),
|
||||
Format35msf(null, 6),
|
||||
Format3rc(Instruction3rc.Factory, 6),
|
||||
Format3rms(Instruction3rms.Factory, 6),
|
||||
Format3rmsf(null, 6),
|
||||
Format51l(Instruction51l.Factory, 10),
|
||||
ArrayData(null, -1, true),
|
||||
PackedSwitchData(null, -1, true),
|
||||
SparseSwitchData(null, -1, true),
|
||||
UnresolvedNullReference(null, -1, false),
|
||||
DeadInstruction(null, -1, false)
|
||||
;
|
||||
|
||||
public final Instruction.InstructionFactory Factory;
|
||||
public final int size;
|
||||
public final boolean variableSizeFormat;
|
||||
|
||||
private Format(Instruction.InstructionFactory factory, int size) {
|
||||
this(factory, size, false);
|
||||
}
|
||||
|
||||
private Format(Instruction.InstructionFactory factory, int size, boolean variableSizeFormat) {
|
||||
this.Factory = factory;
|
||||
this.size = size;
|
||||
this.variableSizeFormat = variableSizeFormat;
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,70 @@
|
||||
/*
|
||||
* [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.Output;
|
||||
|
||||
public class Instruction10t extends Instruction implements OffsetInstruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
public static void emit(Output out, Opcode opcode, byte offA) {
|
||||
if (offA == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(offA);
|
||||
}
|
||||
|
||||
private Instruction10t(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.Format10t;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return buffer[bufferIndex + 1];
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
return new Instruction10t(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.Output;
|
||||
|
||||
public class Instruction10t extends Instruction implements OffsetInstruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
public static void emit(Output out, Opcode opcode, byte offA) {
|
||||
if (offA == 0) {
|
||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||
}
|
||||
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(offA);
|
||||
}
|
||||
|
||||
private Instruction10t(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.Format10t;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return buffer[bufferIndex + 1];
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
return new Instruction10t(opcode, buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.Code.Format;
|
||||
|
||||
import org.jf.dexlib.Code.Instruction;
|
||||
import org.jf.dexlib.Code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.Util.Output;
|
||||
|
||||
public class Instruction10x extends Instruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
public static void emit(Output out, Opcode opcode) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(0);
|
||||
}
|
||||
|
||||
public Instruction10x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
super(opcode, buffer, bufferIndex);
|
||||
|
||||
if (buffer[bufferIndex + 1] != 0x00) {
|
||||
throw new RuntimeException("The second byte of the instruction must be 0");
|
||||
}
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format10x;
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
return new Instruction10x(opcode, buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* [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.DexFile;
|
||||
import org.jf.dexlib.Util.Output;
|
||||
|
||||
public class Instruction10x extends Instruction {
|
||||
public static final InstructionFactory Factory = new Factory();
|
||||
|
||||
public static void emit(Output out, Opcode opcode) {
|
||||
out.writeByte(opcode.value);
|
||||
out.writeByte(0);
|
||||
}
|
||||
|
||||
public Instruction10x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
super(opcode, buffer, bufferIndex);
|
||||
|
||||
if (buffer[bufferIndex + 1] != 0x00) {
|
||||
throw new RuntimeException("The second byte of the instruction must be 0");
|
||||
}
|
||||
}
|
||||
|
||||
public Format getFormat() {
|
||||
return Format.Format10x;
|
||||
}
|
||||
|
||||
private static class Factory implements InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
return new Instruction10x(opcode, buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* [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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<PackedSwitchTarget> getTargets() {
|
||||
return new Iterator<PackedSwitchTarget>() {
|
||||
final int targetCount = getTargetCount();
|
||||
int i = 0;
|
||||
int position = bufferIndex + 8;
|
||||
int value = getFirstKey();
|
||||
|
||||
PackedSwitchTarget packedSwitchTarget = new PackedSwitchTarget();
|
||||
|
||||
public boolean hasNext() {
|
||||
return i<targetCount;
|
||||
}
|
||||
|
||||
public PackedSwitchTarget next() {
|
||||
packedSwitchTarget.value = value++;
|
||||
packedSwitchTarget.target = NumberUtils.decodeInt(buffer, position);
|
||||
position+=4;
|
||||
i++;
|
||||
return packedSwitchTarget;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static interface PackedSwitchTargetIteratorDelegate {
|
||||
void ProcessPackedSwitchTarget(int value, int target);
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for a PackedSwitchDataPseudoInstruction must by NOP");
|
||||
}
|
||||
return new PackedSwitchDataPseudoInstruction(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.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<PackedSwitchTarget> getTargets() {
|
||||
return new Iterator<PackedSwitchTarget>() {
|
||||
final int targetCount = getTargetCount();
|
||||
int i = 0;
|
||||
int position = bufferIndex + 8;
|
||||
int value = getFirstKey();
|
||||
|
||||
PackedSwitchTarget packedSwitchTarget = new PackedSwitchTarget();
|
||||
|
||||
public boolean hasNext() {
|
||||
return i<targetCount;
|
||||
}
|
||||
|
||||
public PackedSwitchTarget next() {
|
||||
packedSwitchTarget.value = value++;
|
||||
packedSwitchTarget.target = NumberUtils.decodeInt(buffer, position);
|
||||
position+=4;
|
||||
i++;
|
||||
return packedSwitchTarget;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static interface PackedSwitchTargetIteratorDelegate {
|
||||
void ProcessPackedSwitchTarget(int value, int target);
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for a PackedSwitchDataPseudoInstruction must by NOP");
|
||||
}
|
||||
return new PackedSwitchDataPseudoInstruction(buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,152 +1,151 @@
|
||||
/*
|
||||
* [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 SparseSwitchDataPseudoInstruction extends Instruction {
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return getTargetCount() * 8 + 4;
|
||||
}
|
||||
|
||||
public static void emit(Output out, int[] keys, int[] targets) {
|
||||
if (keys.length != targets.length) {
|
||||
throw new RuntimeException("The number of keys and offsets don't match");
|
||||
}
|
||||
|
||||
if (targets.length == 0) {
|
||||
throw new RuntimeException("The sparse-switch data must contain at least 1 key/target");
|
||||
}
|
||||
|
||||
if (targets.length > 0xFFFF) {
|
||||
throw new RuntimeException("The sparse-switch data contains too many elements. " +
|
||||
"The maximum number of switch elements is 65535");
|
||||
}
|
||||
|
||||
//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<SparseSwitchTarget> getTargets() {
|
||||
return new Iterator<SparseSwitchTarget>() {
|
||||
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<targetCount;
|
||||
}
|
||||
|
||||
public SparseSwitchTarget next() {
|
||||
sparseSwitchTarget.value = NumberUtils.decodeInt(buffer, valuePosition);
|
||||
sparseSwitchTarget.target = NumberUtils.decodeInt(buffer, targetPosition);
|
||||
valuePosition+=4;
|
||||
targetPosition+=4;
|
||||
i++;
|
||||
return sparseSwitchTarget;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for a SparseSwitchDataPseudoInstruction must by NOP");
|
||||
}
|
||||
return new SparseSwitchDataPseudoInstruction(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.Util.NumberUtils;
|
||||
import org.jf.dexlib.Util.Output;
|
||||
import org.jf.dexlib.DexFile;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class SparseSwitchDataPseudoInstruction extends Instruction {
|
||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return getTargetCount() * 8 + 4;
|
||||
}
|
||||
|
||||
public static void emit(Output out, int[] keys, int[] targets) {
|
||||
if (keys.length != targets.length) {
|
||||
throw new RuntimeException("The number of keys and offsets don't match");
|
||||
}
|
||||
|
||||
if (targets.length == 0) {
|
||||
throw new RuntimeException("The sparse-switch data must contain at least 1 key/target");
|
||||
}
|
||||
|
||||
if (targets.length > 0xFFFF) {
|
||||
throw new RuntimeException("The sparse-switch data contains too many elements. " +
|
||||
"The maximum number of switch elements is 65535");
|
||||
}
|
||||
|
||||
//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<SparseSwitchTarget> getTargets() {
|
||||
return new Iterator<SparseSwitchTarget>() {
|
||||
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<targetCount;
|
||||
}
|
||||
|
||||
public SparseSwitchTarget next() {
|
||||
sparseSwitchTarget.value = NumberUtils.decodeInt(buffer, valuePosition);
|
||||
sparseSwitchTarget.target = NumberUtils.decodeInt(buffer, targetPosition);
|
||||
valuePosition+=4;
|
||||
targetPosition+=4;
|
||||
i++;
|
||||
return sparseSwitchTarget;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class Factory implements Instruction.InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
if (opcode != Opcode.NOP) {
|
||||
throw new RuntimeException("The opcode for a SparseSwitchDataPseudoInstruction must by NOP");
|
||||
}
|
||||
return new SparseSwitchDataPseudoInstruction(buffer, bufferIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Code.Format.Format;
|
||||
|
||||
public abstract class Instruction {
|
||||
public final Opcode opcode;
|
||||
protected final byte[] buffer;
|
||||
protected final int bufferIndex;
|
||||
|
||||
public int getSize() {
|
||||
return opcode.format.size;
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode) {
|
||||
this.opcode = opcode;
|
||||
|
||||
this.bufferIndex = 0;
|
||||
this.buffer = new byte[opcode.format.size];
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode, int bufferSize) {
|
||||
this.opcode = opcode;
|
||||
|
||||
this.bufferIndex = 0;
|
||||
this.buffer = new byte[bufferSize];
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
this.opcode = opcode;
|
||||
|
||||
this.buffer = buffer;
|
||||
this.bufferIndex = bufferIndex;
|
||||
|
||||
if (buffer[bufferIndex] != opcode.value) {
|
||||
throw new RuntimeException("The given opcode doesn't match the opcode byte");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Format getFormat();
|
||||
|
||||
public static interface InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int 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;
|
||||
|
||||
import org.jf.dexlib.*;
|
||||
import org.jf.dexlib.Code.Format.Format;
|
||||
|
||||
public abstract class Instruction {
|
||||
public final Opcode opcode;
|
||||
protected final byte[] buffer;
|
||||
protected final int bufferIndex;
|
||||
|
||||
public int getSize() {
|
||||
return opcode.format.size;
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode) {
|
||||
this.opcode = opcode;
|
||||
|
||||
this.bufferIndex = 0;
|
||||
this.buffer = new byte[opcode.format.size];
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode, int bufferSize) {
|
||||
this.opcode = opcode;
|
||||
|
||||
this.bufferIndex = 0;
|
||||
this.buffer = new byte[bufferSize];
|
||||
}
|
||||
|
||||
protected Instruction(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||
this.opcode = opcode;
|
||||
|
||||
this.buffer = buffer;
|
||||
this.bufferIndex = bufferIndex;
|
||||
|
||||
if (buffer[bufferIndex] != opcode.value) {
|
||||
throw new RuntimeException("The given opcode doesn't match the opcode byte");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Format getFormat();
|
||||
|
||||
public static interface InstructionFactory {
|
||||
public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex);
|
||||
}
|
||||
}
|
||||
|
@ -1,310 +1,310 @@
|
||||
/*
|
||||
* [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<Integer, Opcode> opcodesByName;
|
||||
|
||||
static {
|
||||
opcodesByValue = new Opcode[256];
|
||||
opcodesByName = new HashMap<Integer, Opcode>();
|
||||
|
||||
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<Integer, Opcode> opcodesByName;
|
||||
|
||||
static {
|
||||
opcodesByValue = new Opcode[256];
|
||||
opcodesByName = new HashMap<Integer, Opcode>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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<EncodedArrayItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private ArrayEncodedSubValue encodedArray;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>EncodedArrayItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected EncodedArrayItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>EncodedArrayItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param encodedArray The encoded array value
|
||||
*/
|
||||
private EncodedArrayItem(DexFile dexFile, ArrayEncodedSubValue encodedArray) {
|
||||
super(dexFile);
|
||||
this.encodedArray = encodedArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>EncodedArrayItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param encodedArray The encoded array value
|
||||
* @return an <code>EncodedArrayItem</code> for the given values, and that has been interned into the given
|
||||
*/
|
||||
public static EncodedArrayItem 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<EncodedArrayItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private ArrayEncodedSubValue encodedArray;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>EncodedArrayItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected EncodedArrayItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>EncodedArrayItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param encodedArray The encoded array value
|
||||
*/
|
||||
private EncodedArrayItem(DexFile dexFile, ArrayEncodedSubValue encodedArray) {
|
||||
super(dexFile);
|
||||
this.encodedArray = encodedArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <code>EncodedArrayItem</code> for the given values, and that has been interned into the given
|
||||
* <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param encodedArray The encoded array value
|
||||
* @return an <code>EncodedArrayItem</code> for the given values, and that has been interned into the given
|
||||
*/
|
||||
public static EncodedArrayItem 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);
|
||||
}
|
||||
}
|
||||
|
@ -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 <code>ValueType</code> by byte value
|
||||
*/
|
||||
private final static SparseArray<ValueType> valueTypeIntegerMap;
|
||||
|
||||
static {
|
||||
/** build the <code>valueTypeIntegerMap</code> object */
|
||||
valueTypeIntegerMap = new SparseArray<ValueType>(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 <code>ValueType</code> by byte value
|
||||
*/
|
||||
private final static SparseArray<ValueType> valueTypeIntegerMap;
|
||||
|
||||
static {
|
||||
/** build the <code>valueTypeIntegerMap</code> object */
|
||||
valueTypeIntegerMap = new SparseArray<ValueType>(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);
|
||||
}
|
||||
}
|
@ -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<FieldIdItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private TypeIdItem classType;
|
||||
private TypeIdItem fieldType;
|
||||
private StringIdItem fieldName;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>FieldIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected FieldIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>FieldIdItem</code> for the given class, type and name
|
||||
* @param dexFile The <code>DexFile</code> 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 <code>FieldIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType the class that the field is a member of
|
||||
* @param fieldType the type of the field
|
||||
* @param fieldName the name of the field
|
||||
* @return a <code>FieldIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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<FieldIdItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private TypeIdItem classType;
|
||||
private TypeIdItem fieldType;
|
||||
private StringIdItem fieldName;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>FieldIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected FieldIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>FieldIdItem</code> for the given class, type and name
|
||||
* @param dexFile The <code>DexFile</code> 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 <code>FieldIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType the class that the field is a member of
|
||||
* @param fieldType the type of the field
|
||||
* @param fieldName the name of the field
|
||||
* @return a <code>FieldIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
@ -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<HeaderItem> {
|
||||
/**
|
||||
* 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 <code>HeaderItem</code>
|
||||
* @param dexFile The <code>DexFile</code> containing this <code>HeaderItem</code>
|
||||
*/
|
||||
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<HeaderItem> {
|
||||
/**
|
||||
* 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 <code>HeaderItem</code>
|
||||
* @param dexFile The <code>DexFile</code> containing this <code>HeaderItem</code>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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<T extends Item> extends Section<T> {
|
||||
|
||||
/**
|
||||
* Create a new indexed section
|
||||
* @param dexFile The <code>DexFile</code> 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<T extends Item> extends Section<T> {
|
||||
|
||||
/**
|
||||
* Create a new indexed section
|
||||
* @param dexFile The <code>DexFile</code> 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);
|
||||
}
|
||||
}
|
@ -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<T extends Item> implements Comparable<T> {
|
||||
/**
|
||||
* 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 <code>DexFile</code>
|
||||
* @param dexFile the <code>DexFile</code> 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 <code>Input</code> object to read from
|
||||
* @param index the index within the containing section of the item being read in
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>Input</code> object to read from
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>AnnotatedOutput</code> 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 <code>DexFile</code> 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<T extends Item> implements Comparable<T> {
|
||||
/**
|
||||
* 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 <code>DexFile</code>
|
||||
* @param dexFile the <code>DexFile</code> 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 <code>Input</code> object to read from
|
||||
* @param index the index within the containing section of the item being read in
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>Input</code> object to read from
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>AnnotatedOutput</code> 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 <code>DexFile</code> that contains this item
|
||||
*/
|
||||
public DexFile getDexFile() {
|
||||
return dexFile;
|
||||
}
|
||||
}
|
||||
|
@ -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<MapItem> {
|
||||
/**
|
||||
* 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 <code>MapItem</code>
|
||||
* @param dexFile The <code>DexFile</code> 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<size; i++) {
|
||||
ItemType itemType = ItemType.fromInt(in.readShort());
|
||||
|
||||
//unused
|
||||
in.readShort();
|
||||
|
||||
int sectionSize = in.readInt();
|
||||
int sectionOffset = in.readInt();
|
||||
|
||||
readContext.addSection(itemType, sectionSize, sectionOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
assert getOffset() > 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<MapItem> {
|
||||
/**
|
||||
* 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 <code>MapItem</code>
|
||||
* @param dexFile The <code>DexFile</code> 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<size; i++) {
|
||||
ItemType itemType = ItemType.fromInt(in.readShort());
|
||||
|
||||
//unused
|
||||
in.readShort();
|
||||
|
||||
int sectionSize = in.readInt();
|
||||
int sectionOffset = in.readInt();
|
||||
|
||||
readContext.addSection(itemType, sectionSize, sectionOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
assert getOffset() > 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";
|
||||
}
|
||||
}
|
||||
|
@ -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<MethodIdItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private TypeIdItem classType;
|
||||
private ProtoIdItem methodPrototype;
|
||||
private StringIdItem methodName;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>MethodIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected MethodIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>MethodIdItem</code> for the given class, type and name
|
||||
* @param dexFile The <code>DexFile</code> 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 <code>MethodIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType the class that the method is a member of
|
||||
* @param methodPrototype the type of the method
|
||||
* @param methodName the name of the method
|
||||
* @return a <code>MethodIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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<MethodIdItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private TypeIdItem classType;
|
||||
private ProtoIdItem methodPrototype;
|
||||
private StringIdItem methodName;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>MethodIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected MethodIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>MethodIdItem</code> for the given class, type and name
|
||||
* @param dexFile The <code>DexFile</code> 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 <code>MethodIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param classType the class that the method is a member of
|
||||
* @param methodPrototype the type of the method
|
||||
* @param methodName the name of the method
|
||||
* @return a <code>MethodIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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<T extends Item> extends Section<T> {
|
||||
public OffsettedSection(DexFile dexFile, ItemType itemType) {
|
||||
super(dexFile, itemType);
|
||||
}
|
||||
|
||||
public void readItems(Input in, ReadContext readContext) {
|
||||
SparseArray<T> precreatedItems = (SparseArray<T>)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<T extends Item> extends Section<T> {
|
||||
public OffsettedSection(DexFile dexFile, ItemType itemType) {
|
||||
super(dexFile, itemType);
|
||||
}
|
||||
|
||||
public void readItems(Input in, ReadContext readContext) {
|
||||
SparseArray<T> precreatedItems = (SparseArray<T>)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);
|
||||
}
|
||||
}
|
||||
|
@ -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<ProtoIdItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private StringIdItem shortyDescriptor;
|
||||
private TypeIdItem returnType;
|
||||
private TypeListItem parameters;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>ProtoIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected ProtoIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ProtoIdItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param returnType the return type
|
||||
* @param parameters a <code>TypeListItem</code> 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 <code>ProtoIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param returnType the return type
|
||||
* @param parameters a <code>TypeListItem</code> containing a list of the parameter types
|
||||
* @return a <code>ProtoIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>TypeListItem</code> containing the method parameter types
|
||||
*/
|
||||
public TypeListItem getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of registers required for the parameters of this <code>ProtoIdItem</code>
|
||||
*/
|
||||
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<ProtoIdItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private StringIdItem shortyDescriptor;
|
||||
private TypeIdItem returnType;
|
||||
private TypeListItem parameters;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>ProtoIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected ProtoIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ProtoIdItem</code> with the given values
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param returnType the return type
|
||||
* @param parameters a <code>TypeListItem</code> 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 <code>ProtoIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param returnType the return type
|
||||
* @param parameters a <code>TypeListItem</code> containing a list of the parameter types
|
||||
* @return a <code>ProtoIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>TypeListItem</code> containing the method parameter types
|
||||
*/
|
||||
public TypeListItem getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of registers required for the parameters of this <code>ProtoIdItem</code>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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<T extends Item> {
|
||||
/**
|
||||
* 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<T> 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<T,T> uniqueItems = null;
|
||||
|
||||
/**
|
||||
* The offset of this section within the <code>DexFile</code>
|
||||
*/
|
||||
protected int offset = 0;
|
||||
|
||||
/**
|
||||
* The type of item that this section holds
|
||||
*/
|
||||
public final ItemType ItemType;
|
||||
|
||||
/**
|
||||
* The <code>DexFile</code> that this section belongs to
|
||||
*/
|
||||
public final DexFile DexFile;
|
||||
|
||||
/**
|
||||
* Create a new section
|
||||
* @param dexFile The <code>DexFile</code> 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<T>();
|
||||
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 <code>AnnotatedOutput</code>
|
||||
* @param out the <code>AnnotatedOutput</code> 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 <code>Input</code> object
|
||||
* @param size The number of items to read
|
||||
* @param in The <code>Input</code> object to read from
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>Input</code>
|
||||
* 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 <code>Input</code>
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>List</code> object containing the items in this section
|
||||
*/
|
||||
public List<T> 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<T,T>();
|
||||
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<T extends Item> {
|
||||
/**
|
||||
* 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<T> 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<T,T> uniqueItems = null;
|
||||
|
||||
/**
|
||||
* The offset of this section within the <code>DexFile</code>
|
||||
*/
|
||||
protected int offset = 0;
|
||||
|
||||
/**
|
||||
* The type of item that this section holds
|
||||
*/
|
||||
public final ItemType ItemType;
|
||||
|
||||
/**
|
||||
* The <code>DexFile</code> that this section belongs to
|
||||
*/
|
||||
public final DexFile DexFile;
|
||||
|
||||
/**
|
||||
* Create a new section
|
||||
* @param dexFile The <code>DexFile</code> 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<T>();
|
||||
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 <code>AnnotatedOutput</code>
|
||||
* @param out the <code>AnnotatedOutput</code> 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 <code>Input</code> object
|
||||
* @param size The number of items to read
|
||||
* @param in The <code>Input</code> object to read from
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>Input</code>
|
||||
* 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 <code>Input</code>
|
||||
* @param readContext a <code>ReadContext</code> 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 <code>List</code> object containing the items in this section
|
||||
*/
|
||||
public List<T> 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<T,T>();
|
||||
for (T item: items) {
|
||||
assert item != null;
|
||||
uniqueItems.put(item, item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the items in the section
|
||||
*/
|
||||
protected void sortSection() {
|
||||
Collections.sort(items);
|
||||
}
|
||||
}
|
@ -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<StringDataItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private String stringValue;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>StringDataItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected StringDataItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>StringDataItem</code> for the given string
|
||||
* @param dexFile The <code>DexFile</code> 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 <code>StringDataItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param value The string value that this item represents
|
||||
* @return a <code>StringDataItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>String</code>
|
||||
* @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<StringDataItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private String stringValue;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>StringDataItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected StringDataItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>StringDataItem</code> for the given string
|
||||
* @param dexFile The <code>DexFile</code> 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 <code>StringDataItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param value The string value that this item represents
|
||||
* @return a <code>StringDataItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>String</code>
|
||||
* @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());
|
||||
}
|
||||
}
|
||||
|
@ -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<StringIdItem> {
|
||||
private StringDataItem stringDataItem;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>StringIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected StringIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>StringIdItem</code> for the given <code>StringDataItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param stringDataItem The <code>StringDataItem</code> that this <code>StringIdItem</code> represents
|
||||
*/
|
||||
protected StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
|
||||
super(dexFile);
|
||||
this.stringDataItem = stringDataItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>StringIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param stringValue The string value that this item represents
|
||||
* @return a <code>StringIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>String</code> value that this <code>StringIdItem</code> represents
|
||||
* @return the <code>String</code> value that this <code>StringIdItem</code> represents
|
||||
*/
|
||||
public String getStringValue() {
|
||||
return stringDataItem.getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>StringDataItem</code> that this <code>StringIdItem</code> references
|
||||
* @return the <code>StringDataItem</code> that this <code>StringIdItem</code> 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<StringIdItem> {
|
||||
private StringDataItem stringDataItem;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>StringIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected StringIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>StringIdItem</code> for the given <code>StringDataItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param stringDataItem The <code>StringDataItem</code> that this <code>StringIdItem</code> represents
|
||||
*/
|
||||
protected StringIdItem(DexFile dexFile, StringDataItem stringDataItem) {
|
||||
super(dexFile);
|
||||
this.stringDataItem = stringDataItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>StringIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param stringValue The string value that this item represents
|
||||
* @return a <code>StringIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>String</code> value that this <code>StringIdItem</code> represents
|
||||
* @return the <code>String</code> value that this <code>StringIdItem</code> represents
|
||||
*/
|
||||
public String getStringValue() {
|
||||
return stringDataItem.getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>StringDataItem</code> that this <code>StringIdItem</code> references
|
||||
* @return the <code>StringDataItem</code> that this <code>StringIdItem</code> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<TypeIdItem> {
|
||||
private StringIdItem typeDescriptor;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>TypeIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected TypeIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TypeIdItem</code> for the given <code>StringIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param typeDescriptor The <code>StringIdItem</code> containing the type descriptor that
|
||||
* this <code>TypeIdItem</code> represents
|
||||
*/
|
||||
private TypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
|
||||
super(dexFile);
|
||||
this.typeDescriptor = typeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param typeDescriptor The <code>StringIdItem</code> containing the type descriptor that
|
||||
* this <code>TypeIdItem</code> represents
|
||||
* @return a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
public static TypeIdItem getInternedTypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
|
||||
TypeIdItem typeIdItem = new TypeIdItem(dexFile, typeDescriptor);
|
||||
return dexFile.TypeIdsSection.intern(typeIdItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param typeDescriptor The string containing the type descriptor that this
|
||||
* <code>TypeIdItem</code> represents
|
||||
* @return a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>String</code> for this type
|
||||
* @return the type descriptor as a <code>String</code> 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<TypeIdItem> {
|
||||
private StringIdItem typeDescriptor;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>TypeIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected TypeIdItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TypeIdItem</code> for the given <code>StringIdItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param typeDescriptor The <code>StringIdItem</code> containing the type descriptor that
|
||||
* this <code>TypeIdItem</code> represents
|
||||
*/
|
||||
private TypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
|
||||
super(dexFile);
|
||||
this.typeDescriptor = typeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param typeDescriptor The <code>StringIdItem</code> containing the type descriptor that
|
||||
* this <code>TypeIdItem</code> represents
|
||||
* @return a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
public static TypeIdItem getInternedTypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
|
||||
TypeIdItem typeIdItem = new TypeIdItem(dexFile, typeDescriptor);
|
||||
return dexFile.TypeIdsSection.intern(typeIdItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item will belong to
|
||||
* @param typeDescriptor The string containing the type descriptor that this
|
||||
* <code>TypeIdItem</code> represents
|
||||
* @return a <code>TypeIdItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
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 <code>String</code> for this type
|
||||
* @return the type descriptor as a <code>String</code> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<TypeListItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private TypeIdItem[] typeList;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>TypeListItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected TypeListItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TypeListItem</code> for the given string
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param typeList A list of the types that this <code>TypeListItem</code> represents
|
||||
*/
|
||||
private TypeListItem(DexFile dexFile, TypeIdItem[] typeList) {
|
||||
super(dexFile);
|
||||
|
||||
this.typeList = typeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TypeListItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param typeList A list of the types that this <code>TypeListItem</code> represents
|
||||
* @return a <code>TypeListItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
public static TypeListItem getInternedTypeListItem(DexFile dexFile, List<TypeIdItem> 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<size; i++) {
|
||||
int typeIndex = in.readShort();
|
||||
typeList[i] = dexFile.TypeIdsSection.getItemByIndex(typeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 4 + typeList.length * 2;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
//yes, the code to write the item is duplicated. This eliminates the need to iterate over the list twice
|
||||
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "size: 0x" + Integer.toHexString(typeList.length) + " (" + typeList.length +")");
|
||||
|
||||
for (TypeIdItem typeIdItem: typeList) {
|
||||
out.annotate(2, "type_id_item: " + typeIdItem.getTypeDescriptor());
|
||||
}
|
||||
}
|
||||
out.writeInt(typeList.length);
|
||||
for (TypeIdItem typeIdItem: typeList) {
|
||||
out.writeShort(typeIdItem.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_TYPE_LIST;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "type_list: " + getTypeListString("");
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(TypeListItem o) {
|
||||
if (o == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int thisSize = typeList.length;
|
||||
int otherSize = o.typeList.length;
|
||||
int size = Math.min(thisSize, otherSize);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
int result = typeList[i].compareTo(o.typeList[i]);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (thisSize < otherSize) {
|
||||
return -1;
|
||||
} else if (thisSize > otherSize) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of registers required for this <code>TypeListItem</code>
|
||||
*/
|
||||
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 <code>TypeListItem</code>
|
||||
* 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
|
||||
* <code>TypeListItem</code> 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 <code>TypeIdItem</code> to get
|
||||
* @return the <code>TypeIdItem</code> at the given index
|
||||
*/
|
||||
public TypeIdItem getTypeIdItem(int index) {
|
||||
return typeList[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of types in this <code>TypeListItem</code>
|
||||
*/
|
||||
public int getTypeCount() {
|
||||
return typeList.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an array of the <code>TypeIdItems</code> in this <code>TypeListItem</code>
|
||||
*/
|
||||
public List<TypeIdItem> getTypes() {
|
||||
return new ReadOnlyArrayList<TypeIdItem>(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<typeList.length; i++) {
|
||||
if (typeList[i] != other.typeList[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* [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<TypeListItem> {
|
||||
private int hashCode = 0;
|
||||
|
||||
private TypeIdItem[] typeList;
|
||||
|
||||
/**
|
||||
* Creates a new uninitialized <code>TypeListItem</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
*/
|
||||
protected TypeListItem(DexFile dexFile) {
|
||||
super(dexFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TypeListItem</code> for the given string
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param typeList A list of the types that this <code>TypeListItem</code> represents
|
||||
*/
|
||||
private TypeListItem(DexFile dexFile, TypeIdItem[] typeList) {
|
||||
super(dexFile);
|
||||
|
||||
this.typeList = typeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TypeListItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||
* @param typeList A list of the types that this <code>TypeListItem</code> represents
|
||||
* @return a <code>TypeListItem</code> for the given values, and that has been interned into
|
||||
* the given <code>DexFile</code>
|
||||
*/
|
||||
public static TypeListItem getInternedTypeListItem(DexFile dexFile, List<TypeIdItem> 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<size; i++) {
|
||||
int typeIndex = in.readShort();
|
||||
typeList[i] = dexFile.TypeIdsSection.getItemByIndex(typeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected int placeItem(int offset) {
|
||||
return offset + 4 + typeList.length * 2;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
protected void writeItem(AnnotatedOutput out) {
|
||||
//yes, the code to write the item is duplicated. This eliminates the need to iterate over the list twice
|
||||
|
||||
if (out.annotates()) {
|
||||
out.annotate(4, "size: 0x" + Integer.toHexString(typeList.length) + " (" + typeList.length +")");
|
||||
|
||||
for (TypeIdItem typeIdItem: typeList) {
|
||||
out.annotate(2, "type_id_item: " + typeIdItem.getTypeDescriptor());
|
||||
}
|
||||
}
|
||||
out.writeInt(typeList.length);
|
||||
for (TypeIdItem typeIdItem: typeList) {
|
||||
out.writeShort(typeIdItem.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public ItemType getItemType() {
|
||||
return ItemType.TYPE_TYPE_LIST;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getConciseIdentity() {
|
||||
return "type_list: " + getTypeListString("");
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int compareTo(TypeListItem o) {
|
||||
if (o == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int thisSize = typeList.length;
|
||||
int otherSize = o.typeList.length;
|
||||
int size = Math.min(thisSize, otherSize);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
int result = typeList[i].compareTo(o.typeList[i]);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (thisSize < otherSize) {
|
||||
return -1;
|
||||
} else if (thisSize > otherSize) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of registers required for this <code>TypeListItem</code>
|
||||
*/
|
||||
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 <code>TypeListItem</code>
|
||||
* 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
|
||||
* <code>TypeListItem</code> 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 <code>TypeIdItem</code> to get
|
||||
* @return the <code>TypeIdItem</code> at the given index
|
||||
*/
|
||||
public TypeIdItem getTypeIdItem(int index) {
|
||||
return typeList[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of types in this <code>TypeListItem</code>
|
||||
*/
|
||||
public int getTypeCount() {
|
||||
return typeList.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an array of the <code>TypeIdItems</code> in this <code>TypeListItem</code>
|
||||
*/
|
||||
public List<TypeIdItem> getTypes() {
|
||||
return new ReadOnlyArrayList<TypeIdItem>(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<typeList.length; i++) {
|
||||
if (typeList[i] != other.typeList[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,175 +1,175 @@
|
||||
/*
|
||||
* [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<String, AccessFlags> accessFlagsByName;
|
||||
|
||||
static {
|
||||
accessFlagsByName = new HashMap<String, AccessFlags>();
|
||||
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<String, AccessFlags> accessFlagsByName;
|
||||
|
||||
static {
|
||||
accessFlagsByName = new HashMap<String, AccessFlags>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
* <code>byte[]</code> instance.
|
||||
*
|
||||
* <p><b>Note:</b> As per the {@link Input } interface, multi-byte
|
||||
* reads all use little-endian order.</p>
|
||||
*/
|
||||
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 <code>byte[]</code> of this instance
|
||||
*
|
||||
* @return non-null; the <code>byte[]</code>
|
||||
*/
|
||||
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
|
||||
* <code>byte[]</code> instance.
|
||||
*
|
||||
* <p><b>Note:</b> As per the {@link Input } interface, multi-byte
|
||||
* reads all use little-endian order.</p>
|
||||
*/
|
||||
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 <code>byte[]</code> of this instance
|
||||
*
|
||||
* @return non-null; the <code>byte[]</code>
|
||||
*/
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -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<String> parameterNames = new ArrayList<String>();
|
||||
private ArrayList<Event> events = new ArrayList<Event>();
|
||||
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<Item> referencedItems = new ArrayList<Item>();
|
||||
|
||||
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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<String> parameterNames = new ArrayList<String>();
|
||||
private ArrayList<Event> events = new ArrayList<Event>();
|
||||
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<Item> referencedItems = new ArrayList<Item>();
|
||||
|
||||
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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> 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<Item> referencedItems) {
|
||||
emitAdvancePC(out, address);
|
||||
emitSetFile(out);
|
||||
if (fileName != null) {
|
||||
referencedItems.add(StringIdItem.getInternedStringIdItem(dexFile, fileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
* <code>java.util.DataInput</code>, but no <code>IOExceptions</code>
|
||||
* 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 <code>getCursor() !=
|
||||
* expectedCursor</code>
|
||||
*/
|
||||
public void assertCursor(int expectedCursor);
|
||||
|
||||
/**
|
||||
* Reads a <code>byte</code> from this instance.
|
||||
*
|
||||
* @return the byte value that was read
|
||||
*/
|
||||
public byte readByte();
|
||||
|
||||
/**
|
||||
* Reads a <code>short</code> from this instance.
|
||||
*
|
||||
* @return the short value that was read, as an int
|
||||
*/
|
||||
public int readShort();
|
||||
|
||||
/**
|
||||
* Reads an <code>int</code> from this instance.
|
||||
*
|
||||
* @return the unsigned int value that was read
|
||||
*/
|
||||
public int readInt();
|
||||
|
||||
/**
|
||||
* Reads a <code>long</code> 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 <code>byte[]</code> from this instance.
|
||||
*
|
||||
* @param bytes non-null; the buffer to read the data into
|
||||
* @param offset >= 0; offset into <code>bytes</code> 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 <code>byte[]</code> from this instance. This is just
|
||||
* a convenient shorthand for <code>read(bytes, 0, bytes.length)</code>.
|
||||
*
|
||||
* @param bytes non-null; the buffer to read the data into
|
||||
*/
|
||||
public void read(byte[] bytes);
|
||||
|
||||
|
||||
/**
|
||||
* reads a <code>byte[]</code> from this instance
|
||||
*
|
||||
* @param length >= 0; number of bytes to read
|
||||
* @return a byte array containing <code>length</code> bytes
|
||||
*/
|
||||
public byte[] readBytes(int length);
|
||||
|
||||
/**
|
||||
* reads a <code>byte[]</code> 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
|
||||
* <code>java.util.DataInput</code>, but no <code>IOExceptions</code>
|
||||
* 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 <code>getCursor() !=
|
||||
* expectedCursor</code>
|
||||
*/
|
||||
public void assertCursor(int expectedCursor);
|
||||
|
||||
/**
|
||||
* Reads a <code>byte</code> from this instance.
|
||||
*
|
||||
* @return the byte value that was read
|
||||
*/
|
||||
public byte readByte();
|
||||
|
||||
/**
|
||||
* Reads a <code>short</code> from this instance.
|
||||
*
|
||||
* @return the short value that was read, as an int
|
||||
*/
|
||||
public int readShort();
|
||||
|
||||
/**
|
||||
* Reads an <code>int</code> from this instance.
|
||||
*
|
||||
* @return the unsigned int value that was read
|
||||
*/
|
||||
public int readInt();
|
||||
|
||||
/**
|
||||
* Reads a <code>long</code> 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 <code>byte[]</code> from this instance.
|
||||
*
|
||||
* @param bytes non-null; the buffer to read the data into
|
||||
* @param offset >= 0; offset into <code>bytes</code> 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 <code>byte[]</code> from this instance. This is just
|
||||
* a convenient shorthand for <code>read(bytes, 0, bytes.length)</code>.
|
||||
*
|
||||
* @param bytes non-null; the buffer to read the data into
|
||||
*/
|
||||
public void read(byte[] bytes);
|
||||
|
||||
|
||||
/**
|
||||
* reads a <code>byte[]</code> from this instance
|
||||
*
|
||||
* @param length >= 0; number of bytes to read
|
||||
* @return a byte array containing <code>length</code> bytes
|
||||
*/
|
||||
public byte[] readBytes(int length);
|
||||
|
||||
/**
|
||||
* reads a <code>byte[]</code> 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);
|
||||
}
|
||||
|
@ -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<A, B> {
|
||||
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<A, B> {
|
||||
public final A first;
|
||||
public final B second;
|
||||
|
||||
public Pair(A first, B second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Handler> handlers;
|
||||
|
||||
public int catchAllHandlerAddress;
|
||||
|
||||
public TryRange(int startAddress, int endAddress) {
|
||||
this.startAddress = startAddress;
|
||||
this.endAddress = endAddress;
|
||||
this.handlers = new LinkedList<Handler>();
|
||||
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<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> encodeTries() {
|
||||
if (firstTryRange.next == lastTryRange) {
|
||||
return new Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>>(null, null);
|
||||
}
|
||||
|
||||
ArrayList<CodeItem.TryItem> tries = new ArrayList<CodeItem.TryItem>();
|
||||
ArrayList<CodeItem.EncodedCatchHandler> handlers = new ArrayList<CodeItem.EncodedCatchHandler>();
|
||||
|
||||
HashMap<CodeItem.EncodedCatchHandler, CodeItem.EncodedCatchHandler> handlerDict =
|
||||
new HashMap<CodeItem.EncodedCatchHandler, CodeItem.EncodedCatchHandler>();
|
||||
|
||||
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<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>>(tries, handlers);
|
||||
}
|
||||
|
||||
public void addCatchAllHandler(int startAddress, int endAddress, int handlerAddress) {
|
||||
TryRange startRange;
|
||||
TryRange endRange;
|
||||
|
||||
Pair<TryRange, TryRange> 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<TryRange, TryRange> 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<TryRange, TryRange>(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<TryRange, TryRange>(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<TryRange, TryRange>(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<TryRange, TryRange> 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<Handler> handlers;
|
||||
|
||||
public int catchAllHandlerAddress;
|
||||
|
||||
public TryRange(int startAddress, int endAddress) {
|
||||
this.startAddress = startAddress;
|
||||
this.endAddress = endAddress;
|
||||
this.handlers = new LinkedList<Handler>();
|
||||
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<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> encodeTries() {
|
||||
if (firstTryRange.next == lastTryRange) {
|
||||
return new Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>>(null, null);
|
||||
}
|
||||
|
||||
ArrayList<CodeItem.TryItem> tries = new ArrayList<CodeItem.TryItem>();
|
||||
ArrayList<CodeItem.EncodedCatchHandler> handlers = new ArrayList<CodeItem.EncodedCatchHandler>();
|
||||
|
||||
HashMap<CodeItem.EncodedCatchHandler, CodeItem.EncodedCatchHandler> handlerDict =
|
||||
new HashMap<CodeItem.EncodedCatchHandler, CodeItem.EncodedCatchHandler>();
|
||||
|
||||
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<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>>(tries, handlers);
|
||||
}
|
||||
|
||||
public void addCatchAllHandler(int startAddress, int endAddress, int handlerAddress) {
|
||||
TryRange startRange;
|
||||
TryRange endRange;
|
||||
|
||||
Pair<TryRange, TryRange> 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<TryRange, TryRange> 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<TryRange, TryRange>(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<TryRange, TryRange>(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<TryRange, TryRange>(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<TryRange, TryRange> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user