3344 lines
147 KiB
Java
3344 lines
147 KiB
Java
/*
|
|
* This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html.
|
|
*
|
|
* This file is a derivative of code released under the terms listed below.
|
|
*
|
|
* dexlib2 update: Julian Dolby (dolby@us.ibm.com)
|
|
*
|
|
*/
|
|
/*
|
|
*
|
|
* Copyright (c) 2009-2012,
|
|
*
|
|
* Jonathan Bardin <astrosus@gmail.com>
|
|
* Steve Suh <suhsteve@gmail.com>
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3. The names of the contributors may not be used to endorse or promote
|
|
* products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*
|
|
*/
|
|
|
|
package com.ibm.wala.dalvik.classLoader;
|
|
|
|
import static org.jf.dexlib2.AccessFlags.ABSTRACT;
|
|
import static org.jf.dexlib2.AccessFlags.BRIDGE;
|
|
import static org.jf.dexlib2.AccessFlags.DECLARED_SYNCHRONIZED;
|
|
import static org.jf.dexlib2.AccessFlags.FINAL;
|
|
import static org.jf.dexlib2.AccessFlags.NATIVE;
|
|
import static org.jf.dexlib2.AccessFlags.PRIVATE;
|
|
import static org.jf.dexlib2.AccessFlags.PROTECTED;
|
|
import static org.jf.dexlib2.AccessFlags.PUBLIC;
|
|
import static org.jf.dexlib2.AccessFlags.STATIC;
|
|
import static org.jf.dexlib2.AccessFlags.VOLATILE;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.jf.dexlib2.Opcode;
|
|
import org.jf.dexlib2.analysis.ClassPath;
|
|
import org.jf.dexlib2.analysis.ClassPathResolver;
|
|
import org.jf.dexlib2.analysis.MethodAnalyzer;
|
|
import org.jf.dexlib2.iface.AnnotationElement;
|
|
import org.jf.dexlib2.iface.Method;
|
|
import org.jf.dexlib2.iface.TryBlock;
|
|
import org.jf.dexlib2.iface.instruction.SwitchPayload;
|
|
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction;
|
|
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction10t;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction11n;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction11x;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction12x;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction20t;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21c;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21ih;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21lh;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21s;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21t;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22b;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22c;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22s;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22t;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22x;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction23x;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction30t;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction31c;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction31i;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction31t;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction32x;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction3rc;
|
|
import org.jf.dexlib2.iface.instruction.formats.Instruction51l;
|
|
import org.jf.dexlib2.iface.reference.FieldReference;
|
|
import org.jf.dexlib2.iface.reference.StringReference;
|
|
import org.jf.dexlib2.iface.value.ArrayEncodedValue;
|
|
import org.jf.dexlib2.iface.value.EncodedValue;
|
|
import org.jf.dexlib2.iface.value.TypeEncodedValue;
|
|
|
|
import com.ibm.wala.classLoader.CallSiteReference;
|
|
import com.ibm.wala.classLoader.IBytecodeMethod;
|
|
import com.ibm.wala.classLoader.IClass;
|
|
import com.ibm.wala.classLoader.NewSiteReference;
|
|
import com.ibm.wala.dalvik.dex.instructions.ArrayFill;
|
|
import com.ibm.wala.dalvik.dex.instructions.ArrayGet;
|
|
import com.ibm.wala.dalvik.dex.instructions.ArrayGet.Type;
|
|
import com.ibm.wala.dalvik.dex.instructions.ArrayLength;
|
|
import com.ibm.wala.dalvik.dex.instructions.ArrayPut;
|
|
import com.ibm.wala.dalvik.dex.instructions.BinaryLiteralOperation;
|
|
import com.ibm.wala.dalvik.dex.instructions.BinaryOperation;
|
|
import com.ibm.wala.dalvik.dex.instructions.Branch;
|
|
import com.ibm.wala.dalvik.dex.instructions.CheckCast;
|
|
import com.ibm.wala.dalvik.dex.instructions.Constant;
|
|
import com.ibm.wala.dalvik.dex.instructions.GetField;
|
|
import com.ibm.wala.dalvik.dex.instructions.Goto;
|
|
import com.ibm.wala.dalvik.dex.instructions.InstanceOf;
|
|
import com.ibm.wala.dalvik.dex.instructions.Instruction;
|
|
import com.ibm.wala.dalvik.dex.instructions.Invoke;
|
|
import com.ibm.wala.dalvik.dex.instructions.Monitor;
|
|
import com.ibm.wala.dalvik.dex.instructions.New;
|
|
import com.ibm.wala.dalvik.dex.instructions.NewArray;
|
|
import com.ibm.wala.dalvik.dex.instructions.NewArrayFilled;
|
|
import com.ibm.wala.dalvik.dex.instructions.PackedSwitchPad;
|
|
import com.ibm.wala.dalvik.dex.instructions.PutField;
|
|
import com.ibm.wala.dalvik.dex.instructions.Return;
|
|
import com.ibm.wala.dalvik.dex.instructions.SparseSwitchPad;
|
|
import com.ibm.wala.dalvik.dex.instructions.Switch;
|
|
import com.ibm.wala.dalvik.dex.instructions.Throw;
|
|
import com.ibm.wala.dalvik.dex.instructions.UnaryOperation;
|
|
import com.ibm.wala.dalvik.dex.instructions.UnaryOperation.OpID;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.shrikeBT.ExceptionHandler;
|
|
import com.ibm.wala.shrikeBT.IndirectionData;
|
|
import com.ibm.wala.types.ClassLoaderReference;
|
|
import com.ibm.wala.types.Descriptor;
|
|
import com.ibm.wala.types.MethodReference;
|
|
import com.ibm.wala.types.Selector;
|
|
import com.ibm.wala.types.TypeName;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.types.annotations.Annotation;
|
|
import com.ibm.wala.util.strings.Atom;
|
|
import com.ibm.wala.util.strings.ImmutableByteArray;
|
|
|
|
|
|
/**
|
|
* A wrapper around a EncodedMethod object (from dexlib) that represents a method.
|
|
*/
|
|
public class DexIMethod implements IBytecodeMethod<Instruction> {
|
|
|
|
/**
|
|
* The EncodedMethod object for which this DexIMethod is a wrapper.
|
|
*/
|
|
private final Method eMethod;
|
|
|
|
/**
|
|
* The declaring class for this method.
|
|
*/
|
|
protected final DexIClass myClass;
|
|
|
|
/**
|
|
* canonical MethodReference corresponding to this method,
|
|
* construct in the getReference method.
|
|
*/
|
|
private MethodReference methodReference;
|
|
|
|
/**
|
|
* name of the return type for this method,
|
|
* construct in the get return type method.
|
|
*/
|
|
private TypeReference typeReference;
|
|
|
|
private ExceptionHandler[][] handlers;
|
|
|
|
protected InstructionArray instructions;
|
|
|
|
|
|
|
|
private static int totalInsts = 0;
|
|
|
|
public DexIMethod(Method encodedMethod, DexIClass klass) {
|
|
eMethod = encodedMethod;
|
|
myClass = klass;
|
|
}
|
|
|
|
public static int getTotalInsts() {
|
|
return totalInsts;
|
|
}
|
|
|
|
//------------------------------------------
|
|
// Specific methods
|
|
//------------------------------------------
|
|
|
|
/**
|
|
* @return the EncodedMethod object for which this DexIMethod is a wrapper.
|
|
*/
|
|
public Method toEncodedMethod() {
|
|
return eMethod;
|
|
}
|
|
|
|
|
|
//-------------------------------------------
|
|
// IMethod methods
|
|
//-------------------------------------------
|
|
|
|
@Override
|
|
public TypeReference[] getDeclaredExceptions()
|
|
throws UnsupportedOperationException {
|
|
/** BEGIN Custom change: Variable Names in synth. methods */
|
|
if (myClass.getClassDefItem().getAnnotations() == null) {
|
|
return null;
|
|
}
|
|
ArrayList<String> strings = new ArrayList<>();
|
|
Set<? extends org.jf.dexlib2.iface.Annotation> annotationSet = eMethod.getAnnotations();
|
|
/** END Custom change: Variable Names in synth. methods */
|
|
|
|
if (annotationSet != null) {
|
|
for (org.jf.dexlib2.iface.Annotation annotationItem: annotationSet)
|
|
{
|
|
if (annotationItem.getType().contentEquals("Ldalvik/annotation/Throws;")) {
|
|
for (AnnotationElement e : annotationItem.getElements()) {
|
|
for (EncodedValue v : ((ArrayEncodedValue)e.getValue()).getValue()) {
|
|
String tname = ((TypeEncodedValue)v).getValue();
|
|
if (tname.endsWith(";"))
|
|
tname = tname.substring(0,tname.length()-1);
|
|
strings.add(tname);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strings.size() == 0)
|
|
return null;
|
|
|
|
ClassLoaderReference loader = getDeclaringClass().getClassLoader().getReference();
|
|
|
|
TypeReference[] result = new TypeReference[strings.size()];
|
|
for (int i = 0; i < result.length; i++) {
|
|
result[i] = TypeReference.findOrCreate(loader, TypeName.findOrCreate(ImmutableByteArray.make(strings.get(i))));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
@Override
|
|
public String getLocalVariableName(int bcIndex, int localNumber) {
|
|
throw new UnsupportedOperationException("getLocalVariableName not implemented");
|
|
}
|
|
|
|
/**
|
|
* XXX not fully about the + 2.
|
|
* @return the RegisterCount + 2 to make some room for the return and exception register
|
|
* @see com.ibm.wala.classLoader.ShrikeCTMethod#getMaxLocals()
|
|
*/
|
|
public int getMaxLocals() {
|
|
return eMethod.getImplementation().getRegisterCount() + 2;
|
|
}
|
|
|
|
public int getReturnReg() {
|
|
return eMethod.getImplementation().getRegisterCount();
|
|
}
|
|
|
|
public int getExceptionReg() {
|
|
return eMethod.getImplementation().getRegisterCount()+1;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getMaxStackHeight()
|
|
*/
|
|
public int getMaxStackHeight() {
|
|
throw new UnsupportedOperationException("Dex Methods does not use a stack");
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getDescriptor()
|
|
*/
|
|
@Override
|
|
public Descriptor getDescriptor() {
|
|
return getReference().getDescriptor();
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getNumberOfParameters()
|
|
*/
|
|
@Override
|
|
public int getNumberOfParameters() {
|
|
final int number;
|
|
|
|
|
|
if (isStatic() || isClinit()) {
|
|
number = getReference().getNumberOfParameters();
|
|
} else {
|
|
number = getReference().getNumberOfParameters() + 1;
|
|
}
|
|
|
|
return number;
|
|
}
|
|
|
|
public int getNumberOfParameterRegisters() {
|
|
int number = isStatic() || isClinit() ? 0 : 1;
|
|
|
|
for(int i = 0; i < getReference().getNumberOfParameters(); i++) {
|
|
TypeReference ref = getReference().getParameterType(i);
|
|
number += ref.equals(TypeReference.Double) || ref.equals(TypeReference.Long) ? 2 : 1;
|
|
}
|
|
|
|
return number;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getParameterType(int)
|
|
*/
|
|
@Override
|
|
public TypeReference getParameterType(int index) {
|
|
if (!isStatic()) {
|
|
if (index == 0) {
|
|
return myClass.getReference();
|
|
} else {
|
|
return getReference().getParameterType(index - 1);
|
|
}
|
|
} else {
|
|
return getReference().getParameterType(index);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getReference()
|
|
*/
|
|
@Override
|
|
public MethodReference getReference() {
|
|
//Compute the method reference from the MethodIdItem
|
|
if (methodReference == null) {
|
|
// Set method name
|
|
Atom name = Atom.findOrCreateUnicodeAtom(eMethod.getName());
|
|
|
|
// // Set the descriptor
|
|
// Descriptor descriptor = Descriptor.findOrCreateUTF8(eMethod.method.getPrototype().getPrototypeString());
|
|
// methodReference = MethodReference.findOrCreate(myClass.getReference(),name, descriptor);
|
|
|
|
Descriptor D = Descriptor.findOrCreate(myClass.getClassLoader().getLanguage(), ImmutableByteArray.make(DexUtil.getSignature(eMethod)));
|
|
methodReference = MethodReference.findOrCreate(myClass.getReference(), name, D);
|
|
}
|
|
|
|
return methodReference;
|
|
}
|
|
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getReturnType()
|
|
*/
|
|
@Override
|
|
public TypeReference getReturnType() {
|
|
//compute the typeReference from the MethodIdItem
|
|
if (typeReference == null) {
|
|
typeReference = getReference().getReturnType();
|
|
}
|
|
|
|
return typeReference;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#getSelector()
|
|
*/
|
|
@Override
|
|
public Selector getSelector() {
|
|
return getReference().getSelector();
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.wala.classLoader.IMethod#getSignature()
|
|
*/
|
|
@Override
|
|
public String getSignature() {
|
|
return getReference().getSignature();
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#hasExceptionHandler()
|
|
*/
|
|
@Override
|
|
public boolean hasExceptionHandler() {
|
|
List<? extends TryBlock<? extends org.jf.dexlib2.iface.ExceptionHandler>> tries = eMethod.getImplementation().getTryBlocks();
|
|
return tries==null?false:tries.size() > 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#hasLocalVariableTable()
|
|
*/
|
|
@Override
|
|
public boolean hasLocalVariableTable() {
|
|
throw new UnsupportedOperationException("DexIMethod: hasLocalVariableTable() not yet implemented");
|
|
//TODO Compute the local variable name from the DebugInfo Item
|
|
//eMethod.codeItem.getDebugInfo()
|
|
// return false;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isAbstract()
|
|
*/
|
|
@Override
|
|
public boolean isAbstract() {
|
|
return (eMethod.getAccessFlags() & ABSTRACT.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isClinit()
|
|
*/
|
|
@Override
|
|
public boolean isClinit() {
|
|
return eMethod.getName().equals(MethodReference.clinitName.toString());
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isFinal()
|
|
*/
|
|
@Override
|
|
public boolean isFinal() {
|
|
return (eMethod.getAccessFlags() & FINAL.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isInit()
|
|
*/
|
|
@Override
|
|
public boolean isInit() {
|
|
return eMethod.getName().equals(MethodReference.initAtom.toString());
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isNative()
|
|
*/
|
|
@Override
|
|
public boolean isNative() {
|
|
return (eMethod.getAccessFlags() & NATIVE.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isBridge()
|
|
*/
|
|
@Override
|
|
public boolean isBridge() {
|
|
return (eMethod.getAccessFlags() & BRIDGE.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isPrivate()
|
|
*/
|
|
@Override
|
|
public boolean isPrivate() {
|
|
return (eMethod.getAccessFlags() & PRIVATE.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isProtected()
|
|
*/
|
|
@Override
|
|
public boolean isProtected() {
|
|
return (eMethod.getAccessFlags() & PROTECTED.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.wala.classLoader.IMethod#isPublic()
|
|
*/
|
|
@Override
|
|
public boolean isPublic() {
|
|
return (eMethod.getAccessFlags() & PUBLIC.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isSynchronized()
|
|
*/
|
|
@Override
|
|
public boolean isSynchronized() {
|
|
return (eMethod.getAccessFlags() & DECLARED_SYNCHRONIZED.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMethod#isSynthetic()
|
|
*/
|
|
@Override
|
|
public boolean isSynthetic() {
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMember#isStatic()
|
|
*/
|
|
@Override
|
|
public boolean isStatic() {
|
|
return (eMethod.getAccessFlags() & STATIC.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMember#isVolatile()
|
|
*/
|
|
public boolean isVolatile() {
|
|
return (eMethod.getAccessFlags() & VOLATILE.getValue()) != 0;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see com.ibm.wala.classLoader.IMember#getDeclaringClass()
|
|
*/
|
|
@Override
|
|
public IClass getDeclaringClass() {
|
|
return myClass;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.wala.ipa.cha.IClassHierarchyDweller#getClassHierarchy()
|
|
*/
|
|
@Override
|
|
public IClassHierarchy getClassHierarchy() {
|
|
return myClass.getClassHierarchy();
|
|
}
|
|
|
|
@Override
|
|
public Atom getName() {
|
|
return getReference().getName();
|
|
}
|
|
|
|
@Override
|
|
public int getLineNumber(int bcIndex) {
|
|
return getInstructionIndex(bcIndex);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see java.lang.Object#toString()
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
return getReference().toString();
|
|
}
|
|
|
|
/**
|
|
* @see java.lang.Object#equals(Object)
|
|
*/
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
// instanceof is OK because this class is final.
|
|
// if (this.getClass().equals(obj.getClass())) {
|
|
if (obj instanceof DexIMethod) {
|
|
DexIMethod that = (DexIMethod) obj;
|
|
return (getDeclaringClass().equals(that.getDeclaringClass()) && getReference().equals(that.getReference()));
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @see java.lang.Object#hashCode()
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
return 9661 * getReference().hashCode();
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------
|
|
// IByteCodeMethod methods
|
|
// (required to build the ShrikeCFG)
|
|
//-------------------------------------------
|
|
|
|
|
|
@Override
|
|
public int getBytecodeIndex(int i) {
|
|
// TODO Auto-generated method stub
|
|
// System.out.println("DexIMethod: getBytecodeIndex() possibly not implemented correctly");
|
|
// Integer.valueOf(eMethod.codeItem.getInstructions()[i].opcode.value);
|
|
// return i;
|
|
return getAddressFromIndex(i);
|
|
// return -1;
|
|
}
|
|
|
|
|
|
@Override
|
|
public ExceptionHandler[][] getHandlers() {
|
|
|
|
if (handlers != null)
|
|
return handlers;
|
|
|
|
//ExceptionHandler[][] handlers = new ExceptionHandler[eMethod.codeItem.getInstructions().length][];
|
|
|
|
List<? extends TryBlock<? extends org.jf.dexlib2.iface.ExceptionHandler>> tryBlocks = eMethod.getImplementation().getTryBlocks();
|
|
|
|
//
|
|
// if (tries == null){
|
|
// return new ExceptionHandler[eMethod.codeItem.getInstructions().length][];
|
|
// }
|
|
// ExceptionHandler[][] handlers = new ExceptionHandler[tries.length][];
|
|
// for (int i = 0; i < tries.length; i++) {
|
|
// EncodedTypeAddrPair[] etaps = tries[i].encodedCatchHandler.handlers;
|
|
// handlers[i] = new ExceptionHandler[etaps.length];
|
|
// for (int j = 0; j < etaps.length; j++) {
|
|
// EncodedTypeAddrPair etap = etaps[j];
|
|
// handlers[i][j] = new ExceptionHandler(etap.getHandlerAddress(), etap.exceptionType.getTypeDescriptor());
|
|
// }
|
|
// }
|
|
|
|
this.handlers = new ExceptionHandler[instructions().size()][];
|
|
if (tryBlocks == null){
|
|
// return new ExceptionHandler[instructions.size()][];
|
|
return handlers;
|
|
}
|
|
|
|
ArrayList<ArrayList<ExceptionHandler>> temp_array = new ArrayList<>();
|
|
for (int i = 0; i < instructions().size(); i++) {
|
|
temp_array.add(new ArrayList<ExceptionHandler>());
|
|
}
|
|
|
|
for (TryBlock<? extends org.jf.dexlib2.iface.ExceptionHandler> tryItem: tryBlocks) {
|
|
int startAddress = tryItem.getStartCodeAddress();
|
|
int endAddress = tryItem.getStartCodeAddress() + tryItem.getCodeUnitCount();
|
|
/**
|
|
* The end address points to the address immediately after the end of the last
|
|
* instruction that the try block covers. We want the .catch directive and end_try
|
|
* label to be associated with the last covered instruction, so we need to get
|
|
* the address for that instruction
|
|
*/
|
|
|
|
|
|
int startInst = getInstructionIndex(startAddress);
|
|
int endInst;
|
|
/**
|
|
* The try block can extend to the last instruction in the method. If this is the
|
|
* case then endAddress will be the address immediately following the last instruction.
|
|
* Check to make sure this is the case.
|
|
*/
|
|
if (endAddress > getAddressFromIndex(instructions().size()-1)) {
|
|
endInst = instructions().size()-1;
|
|
int endSize = 0;
|
|
for(org.jf.dexlib2.iface.instruction.Instruction inst : eMethod.getImplementation().getInstructions()) {
|
|
endSize = inst.getCodeUnits();
|
|
}
|
|
if (endAddress != (getAddressFromIndex(endInst) + endSize))
|
|
throw new RuntimeException("Invalid code offset " + endAddress + " for the try block end address");
|
|
}
|
|
else {
|
|
endInst = getInstructionIndex(endAddress) - 1;
|
|
}
|
|
|
|
for (int i = startInst; i <= endInst; i++) {
|
|
//add the rest of the handlers
|
|
for (org.jf.dexlib2.iface.ExceptionHandler etaps: tryItem.getExceptionHandlers()) {
|
|
temp_array.get(i).add(new ExceptionHandler( getInstructionIndex(etaps.getHandlerCodeAddress()), etaps.getExceptionType() ));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for (int i = 0; i < instructions().size(); i++) {
|
|
handlers[i] = temp_array.get(i).toArray(new ExceptionHandler[temp_array.get(i).size()]);
|
|
|
|
/*
|
|
System.out.println("i: " + i);
|
|
for (int j = 0; j < handlers[i].length; j++) {
|
|
System.out.println("\t j: " + j);
|
|
System.out.println("\t\t Handler: " + handlers[i][j].getHandler());
|
|
System.out.println("\t\t Catch Class: " + handlers[i][j].getCatchClass());
|
|
}
|
|
*/
|
|
}
|
|
|
|
return handlers;
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
public Instruction[] getInstructions() {
|
|
if (instructions == null)
|
|
parseBytecode();
|
|
|
|
return instructions.toArray(new Instruction[ instructions.size() ]);
|
|
}
|
|
|
|
private boolean odexMethod() {
|
|
for(org.jf.dexlib2.iface.instruction.Instruction inst : eMethod.getImplementation().getInstructions()) {
|
|
if (inst.getOpcode().odexOnly()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Iterable<? extends org.jf.dexlib2.iface.instruction.Instruction> deodex() {
|
|
try {
|
|
DexFileModule m = myClass.getContainer();
|
|
|
|
ClassPathResolver path =
|
|
new ClassPathResolver(Collections.singletonList(m.getFile().getParent() + "/"),
|
|
Collections.<String>emptyList(),
|
|
m.getDexFile());
|
|
|
|
ClassPath cp = new ClassPath(path.getResolvedClassProviders(), false, m.getDexFile().getOpcodes().artVersion);
|
|
|
|
MethodAnalyzer analyzer = new MethodAnalyzer(cp, eMethod, null, false);
|
|
|
|
return analyzer.getInstructions();
|
|
} catch (Exception e) {
|
|
assert false : e;
|
|
return eMethod.getImplementation().getInstructions();
|
|
}
|
|
}
|
|
|
|
protected void parseBytecode() {
|
|
|
|
Iterable<? extends org.jf.dexlib2.iface.instruction.Instruction> instrucs =
|
|
odexMethod()?
|
|
deodex():
|
|
eMethod.getImplementation().getInstructions();
|
|
|
|
// for (org.jfmethod.getInstructionIndex(.dexlib.Code.Instruction inst: instrucs)
|
|
// {
|
|
// switch (inst.getFormat())
|
|
// {
|
|
//
|
|
// case Format10t:
|
|
// instructions.add(new IInstruction10t((Instruction10t)inst, this));
|
|
// break;
|
|
// case Format10x:
|
|
// instructions.add(new IInstruction10x((Instruction10x)inst, this));
|
|
// break;
|
|
// case Format11n:
|
|
// instructions.add(new IInstruction11n((Instruction11n)inst, this));
|
|
// break;
|
|
// case Format11x:
|
|
// instructions.add(new IInstruction11x((Instruction11x)inst, this));
|
|
// break;
|
|
// case Format12x:
|
|
// instructions.add(new IInstruction12x((Instruction12x)inst, this));
|
|
// break;
|
|
// case Format20t:
|
|
// instructions.add(new IInstruction20t((Instruction20t)inst, this));
|
|
// break;
|
|
// case Format21c:
|
|
// instructions.add(new IInstruction21c((Instruction21c)inst, this));
|
|
// break;
|
|
// case Format21h:
|
|
// instructions.add(new IInstruction21h((Instruction21h)inst, this));
|
|
// break;
|
|
// case Format21s:
|
|
// instructions.add(new IInstruction21s((Instruction21s)inst, this));
|
|
// break;
|
|
// case Format21t:
|
|
// instructions.add(new IInstruction21t((Instruction21t)inst, this));
|
|
// break;
|
|
// case Format22b:
|
|
// instructions.add(new IInstruction22b((Instruction22b)inst, this));
|
|
// break;
|
|
// case Format22c:
|
|
// instructions.add(new IInstruction22c((Instruction22c)inst, this));
|
|
// break;
|
|
// case Format22cs:
|
|
// instructions.add(new IInstruction22cs((Instruction22cs)inst, this));
|
|
// break;
|
|
// case Format22s:
|
|
// instructions.add(new IInstruction22s((Instruction22s)inst, this));
|
|
// break;
|
|
// case Format22t:
|
|
// instructions.add(new IInstruction22t((Instruction22t)inst, this));
|
|
// break;
|
|
// case Format22x:
|
|
// instructions.add(new IInstruction22x((Instruction22x)inst, this));
|
|
// break;
|
|
// case Format23x:
|
|
// instructions.add(new IInstruction23x((Instruction23x)inst, this));
|
|
// break;
|
|
// case Format30t:
|
|
// instructions.add(new IInstruction30t((Instruction30t)inst, this));
|
|
// break;
|
|
// case Format31c:
|
|
// instructions.add(new IInstruction31c((Instruction31c)inst, this));
|
|
// break;
|
|
// case Format31i:
|
|
// instructions.add(new IInstruction31i((Instruction31i)inst, this));
|
|
// break;
|
|
// case Format31t:
|
|
// instructions.add(new IInstruction31t((Instruction31t)inst, this));
|
|
// break;
|
|
// case Format32x:
|
|
// instructions.add(new IInstruction32x((Instruction32x)inst, this));
|
|
// break;
|
|
// case Format35c:
|
|
// instructions.add(new IInstruction35c((Instruction35c)inst, this));
|
|
// break;
|
|
// case Format35ms:
|
|
// instructions.add(new IInstruction35ms((Instruction35ms)inst, this));
|
|
// break;
|
|
// case Format35s:
|
|
// instructions.add(new IInstruction35s((Instruction35s)inst, this));
|
|
// break;
|
|
// case Format3rc:
|
|
// instructions.add(new IInstruction3rc((Instruction3rc)inst, this));
|
|
// break;
|
|
// case Format3rms:
|
|
// instructions.add(new IInstruction3rms((Instruction3rms)inst, this));
|
|
// break;
|
|
// case Format51l:
|
|
// instructions.add(new IInstruction51l((Instruction51l)inst, this));
|
|
// break;
|
|
// case ArrayData:
|
|
// instructions.add(new IArrayDataPseudoInstruction((ArrayDataPseudoInstruction)inst, this));
|
|
// break;
|
|
// case PackedSwitchData:
|
|
// instructions.add(new IPackedSwitchDataPseudoInstruction((PackedSwitchDataPseudoInstruction)inst, this));
|
|
// break;
|
|
// case SparseSwitchData:
|
|
// instructions.add(new ISparseSwitchDataPseudoInstruction((SparseSwitchDataPseudoInstruction)inst, this));
|
|
// break;
|
|
// case UnresolvedOdexInstruction:
|
|
// instructions.add(new IUnresolvedOdexInstruction((UnresolvedOdexInstruction)inst, this));
|
|
// break;
|
|
//
|
|
// }
|
|
// }
|
|
|
|
//if (eMethod.method.getMethodString().contentEquals("Lorg/xbill/DNS/Name;-><init>([B)V") && instrucs.length == 4)
|
|
// System.out.println("debug here");
|
|
|
|
|
|
|
|
instructions = new InstructionArray();
|
|
int instLoc = 0;
|
|
int instCounter = -1;
|
|
//int pc = 0;
|
|
int currentCodeAddress = 0;
|
|
for (org.jf.dexlib2.iface.instruction.Instruction inst: instrucs)
|
|
{
|
|
totalInsts++;
|
|
instCounter++;
|
|
// instLoc = pc - instCounter;
|
|
instLoc = currentCodeAddress;
|
|
//pc += inst.getFormat().size;
|
|
switch(inst.getOpcode())
|
|
{
|
|
case NOP:
|
|
case ARRAY_PAYLOAD:
|
|
case PACKED_SWITCH_PAYLOAD:
|
|
case SPARSE_SWITCH_PAYLOAD:
|
|
switch (inst.getOpcode().format)
|
|
{
|
|
case ArrayPayload:
|
|
{
|
|
for (int i = 0; i < instructions.size(); i++)
|
|
{
|
|
if (instructions.getFromId(i) instanceof ArrayFill)
|
|
if (instLoc == (((ArrayFill)getInstructionFromIndex(i)).tableAddressOffset + getAddressFromIndex(i)))
|
|
{
|
|
((ArrayFill)getInstructionFromIndex(i)).setArrayDataTable((ArrayPayload)inst);
|
|
|
|
|
|
|
|
// Iterator<ArrayElement> b = (((ArrayDataPseudoInstruction)inst).getElements());
|
|
// while (b.hasNext())
|
|
// {
|
|
// int ElementWidth = ((ArrayDataPseudoInstruction)inst).getElementWidth();
|
|
// byte[] temp_byte = new byte[ElementWidth];
|
|
//
|
|
// ArrayElement t = (ArrayElement)b.next();
|
|
// for (int j = 0; j < ElementWidth; j++)
|
|
// temp_byte[j] = t.buffer[t.bufferIndex+(ElementWidth-1)-j];
|
|
//
|
|
// ByteBuffer byte_buffer = ByteBuffer.wrap(temp_byte);
|
|
//
|
|
// System.out.println("Index: " + t.bufferIndex + ", Width: " + t.elementWidth + ", Value: " + byte_buffer.getChar());
|
|
// }
|
|
|
|
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case PackedSwitchPayload:
|
|
for (int i = 0; i < instructions.size(); i++)
|
|
{
|
|
if (instructions.getFromId(i) instanceof Switch)
|
|
if (instLoc == (((Switch)getInstructionFromIndex(i)).tableAddressOffset + getAddressFromIndex(i)))
|
|
{
|
|
((Switch)getInstructionFromIndex(i))
|
|
.setSwitchPad(new PackedSwitchPad(
|
|
(SwitchPayload)inst,
|
|
getAddressFromIndex(i+1) - getAddressFromIndex(i)));
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case SparseSwitchPayload:
|
|
{
|
|
for (int i = 0; i < instructions.size(); i++)
|
|
{
|
|
if (instructions.getFromId(i) instanceof Switch)
|
|
if (instLoc == (((Switch)getInstructionFromIndex(i)).tableAddressOffset + getAddressFromIndex(i)))
|
|
{
|
|
((Switch)getInstructionFromIndex(i)).setSwitchPad(
|
|
new SparseSwitchPad(
|
|
(SwitchPayload)inst,
|
|
getAddressFromIndex(i+1) - getAddressFromIndex(i)));
|
|
break;
|
|
}
|
|
}
|
|
// System.out.println("Targets: " + ((SparseSwitchDataPseudoInstruction)inst).getTargetCount());
|
|
// Iterator<SparseSwitchTarget> i = (((SparseSwitchDataPseudoInstruction)inst).iterateKeysAndTargets());
|
|
// while (i.hasNext())
|
|
// {
|
|
// SparseSwitchTarget t = (SparseSwitchTarget)i.next();
|
|
// System.out.println("Key: " + t.key + ", TargetAddressOffset: " + t.targetAddressOffset);
|
|
// }
|
|
break;
|
|
}
|
|
default:
|
|
class NOPInstruction extends Instruction {
|
|
private NOPInstruction(int pc, Opcode op, DexIMethod method) {
|
|
super(pc, op, method);
|
|
}
|
|
|
|
@Override
|
|
public void visit(Visitor visitor) {
|
|
// no op
|
|
}
|
|
}
|
|
|
|
instructions.add(new NOPInstruction(currentCodeAddress, Opcode.NOP, this));
|
|
break;
|
|
}
|
|
break;
|
|
case MOVE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_FROM16:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction22x)inst).getRegisterA(),
|
|
((Instruction22x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_16:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction32x)inst).getRegisterA(),
|
|
((Instruction32x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_WIDE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE_WIDE,
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_WIDE_FROM16:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE_WIDE,
|
|
((Instruction22x)inst).getRegisterA(), ((Instruction22x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_WIDE_16:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE_WIDE,
|
|
((Instruction32x)inst).getRegisterA(), ((Instruction32x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_OBJECT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_OBJECT_FROM16:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction22x)inst).getRegisterA(),
|
|
((Instruction22x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_OBJECT_16:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction32x)inst).getRegisterA(),
|
|
((Instruction32x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_RESULT:
|
|
//register b set as return register, -1;
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction11x)inst).getRegisterA(), getReturnReg(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_RESULT_WIDE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE_WIDE,
|
|
((Instruction11x)inst).getRegisterA(), getReturnReg(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_RESULT_OBJECT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE, ((Instruction11x)inst).getRegisterA(),
|
|
getReturnReg(), inst.getOpcode(), this));
|
|
break;
|
|
case MOVE_EXCEPTION:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
UnaryOperation.OpID.MOVE_EXCEPTION, ((Instruction11x)inst).getRegisterA(),
|
|
getExceptionReg(), inst.getOpcode(), this));
|
|
break;
|
|
case RETURN_VOID:
|
|
case RETURN_VOID_NO_BARRIER:
|
|
instructions.add(new Return.ReturnVoid(instLoc, inst.getOpcode(), this));
|
|
break;
|
|
case RETURN:
|
|
//I think only primitives call return, and objects call return-object
|
|
instructions.add(new Return.ReturnSingle(instLoc,
|
|
((Instruction11x)inst).getRegisterA(), true, inst.getOpcode(), this));
|
|
break;
|
|
case RETURN_WIDE:
|
|
//+1 to second parameter okay?
|
|
instructions.add(new Return.ReturnDouble(instLoc,
|
|
((Instruction11x)inst).getRegisterA(), ((Instruction11x)inst).getRegisterA()+1, inst.getOpcode(), this));
|
|
break;
|
|
case RETURN_OBJECT:
|
|
instructions.add(new Return.ReturnSingle(instLoc,
|
|
((Instruction11x)inst).getRegisterA(), false, inst.getOpcode(), this));
|
|
break;
|
|
case CONST_4: {
|
|
instructions.add(new Constant.IntConstant(instLoc,
|
|
((Instruction11n)inst).getNarrowLiteral(),((Instruction11n)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case CONST_16:
|
|
instructions.add(new Constant.IntConstant(instLoc,
|
|
((Instruction21s)inst).getNarrowLiteral(), ((Instruction21s)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST:
|
|
instructions.add(new Constant.IntConstant(instLoc,
|
|
((Instruction31i)inst).getNarrowLiteral(), ((Instruction31i)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_HIGH16:
|
|
instructions.add(new Constant.IntConstant(instLoc,
|
|
((Instruction21ih)inst).getHatLiteral() << 16, ((Instruction21ih)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_WIDE_16:
|
|
instructions.add(new Constant.LongConstant(instLoc,
|
|
((Instruction21s)inst).getWideLiteral(), ((Instruction21s)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_WIDE_32:
|
|
instructions.add(new Constant.LongConstant(instLoc,
|
|
((Instruction31i)inst).getWideLiteral(), ((Instruction31i)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_WIDE:
|
|
instructions.add(new Constant.LongConstant(instLoc,
|
|
((Instruction51l)inst).getWideLiteral(), ((Instruction51l)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_WIDE_HIGH16:
|
|
instructions.add(new Constant.LongConstant(instLoc,
|
|
((Instruction21lh)inst).getWideLiteral() << 16, ((Instruction21lh)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_STRING:
|
|
|
|
instructions.add(new Constant.StringConstant(instLoc,
|
|
((StringReference)((Instruction21c)inst).getReference()).getString(),
|
|
((Instruction21c)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_STRING_JUMBO:
|
|
instructions.add(new Constant.StringConstant(instLoc,
|
|
((StringReference)((Instruction31c)inst).getReference()).getString(),
|
|
((Instruction31c)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CONST_CLASS: {
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction21c)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
//IClass ic = this.myClass.loader.lookupClass(TypeName.findOrCreate(cname));
|
|
TypeReference typeRef = TypeReference.findOrCreate(myClass.getClassLoader().getReference(), cname);
|
|
|
|
instructions.add(new Constant.ClassConstant(instLoc,
|
|
typeRef, ((Instruction21c)inst).getRegisterA(), inst.getOpcode(), this));
|
|
//logger.debug("myClass found name: " + this.myClass.loader.lookupClass(TypeName.findOrCreate(cname)).toString());
|
|
break;
|
|
}
|
|
case MONITOR_ENTER:
|
|
instructions.add(new Monitor(instLoc, true, ((Instruction11x)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case MONITOR_EXIT:
|
|
instructions.add(new Monitor(instLoc, false, ((Instruction11x)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case CHECK_CAST: {
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction21c)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
//retrieving type reference correctly?
|
|
instructions.add(new CheckCast(instLoc,
|
|
TypeReference.findOrCreate(myClass.getClassLoader().getReference(), cname),
|
|
((Instruction21c)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INSTANCE_OF: {
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction22c)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
instructions.add(new InstanceOf(instLoc,
|
|
((Instruction22c)inst).getRegisterA(),
|
|
TypeReference.findOrCreate(myClass.getClassLoader().getReference(),
|
|
cname),
|
|
((Instruction22c)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case ARRAY_LENGTH:
|
|
instructions.add(new ArrayLength(instLoc,
|
|
((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case NEW_INSTANCE: {
|
|
//newsitereference use instLoc or pc?
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction21c)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
instructions.add(new New(instLoc,
|
|
((Instruction21c)inst).getRegisterA(),
|
|
NewSiteReference.make(instLoc, TypeReference.findOrCreate(myClass.getClassLoader().getReference(),
|
|
cname)), inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case NEW_ARRAY:
|
|
{
|
|
int[] params = new int[1];
|
|
params[0] = ((Instruction22c)inst).getRegisterB();
|
|
// MyLogger.log(LogLevel.INFO, "Type: " +((TypeIdItem)((Instruction22c)inst).getReferencedItem()).getTypeDescriptor());
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction22c)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
instructions.add(new NewArray(instLoc,
|
|
((Instruction22c)inst).getRegisterA(),
|
|
NewSiteReference.make(instLoc, TypeReference.findOrCreate(myClass.getClassLoader().getReference(),
|
|
cname)),
|
|
params, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
//TODO: FILLED ARRAYS
|
|
case FILLED_NEW_ARRAY: {
|
|
int registerCount = ((Instruction35c)inst).getRegisterCount();
|
|
int[] params = new int[1];
|
|
params[0] = registerCount;
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
{
|
|
switch(i) {
|
|
case 0:
|
|
args[0] = ((Instruction35c)inst).getRegisterD();
|
|
break;
|
|
case 1:
|
|
args[1] = ((Instruction35c)inst).getRegisterE();
|
|
break;
|
|
case 2:
|
|
args[2] = ((Instruction35c)inst).getRegisterF();
|
|
break;
|
|
case 3:
|
|
args[3] = ((Instruction35c)inst).getRegisterG();
|
|
break;
|
|
case 4:
|
|
args[4] = ((Instruction35c)inst).getRegisterC();
|
|
break;
|
|
default:
|
|
throw new RuntimeException("Illegal instruction at "
|
|
+ instLoc + ": bad register count");
|
|
}
|
|
}
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction35c)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
NewSiteReference newSiteRef = NewSiteReference.make(instLoc, TypeReference.findOrCreate(myClass.getClassLoader().getReference(),
|
|
cname));
|
|
TypeReference myTypeRef = TypeReference.findOrCreate(myClass.getClassLoader().getReference(), newSiteRef.getDeclaredType().getArrayElementType().getName().toString());
|
|
|
|
instructions.add(new NewArrayFilled(instLoc, getReturnReg(),
|
|
newSiteRef, myTypeRef, params, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case FILLED_NEW_ARRAY_RANGE: {
|
|
int registerCount = ((Instruction3rc)inst).getRegisterCount();
|
|
int[] params = new int[1];
|
|
params[0] = registerCount;
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
args[i] = ((Instruction3rc)inst).getStartRegister() + i;
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.TypeReference)((Instruction3rc)inst).getReference()).getType();
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
NewSiteReference newSiteRef = NewSiteReference.make(instLoc, TypeReference.findOrCreate(myClass.getClassLoader().getReference(),
|
|
cname));
|
|
TypeReference myTypeRef = TypeReference.findOrCreate(myClass.getClassLoader().getReference(), newSiteRef.getDeclaredType().getArrayElementType().getName().toString());
|
|
|
|
|
|
instructions.add(new NewArrayFilled(instLoc, getReturnReg(), newSiteRef, myTypeRef, params, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case FILL_ARRAY_DATA:
|
|
// System.out.println("Array Reference: " + ((Instruction31t)inst).getRegisterA());
|
|
// System.out.println("Table Address Offset: " + ((Instruction31t)inst).getCodeOffset());
|
|
|
|
TypeReference arrayElementType = findOutArrayElementType(inst, instructions.toArray(new Instruction[0]), instCounter);
|
|
instructions.add(new ArrayFill(instLoc, ((Instruction31t)inst).getRegisterA(), ((Instruction31t)inst).getCodeOffset(),
|
|
TypeReference.findOrCreate(myClass.getClassLoader().getReference(), arrayElementType.getName().toString()), inst.getOpcode(), this));
|
|
break;
|
|
case THROW:
|
|
instructions.add(new Throw(instLoc, ((Instruction11x)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case GOTO:
|
|
instructions.add(new Goto(instLoc, ((Instruction10t)inst).getCodeOffset(), inst.getOpcode(), this));
|
|
break;
|
|
case GOTO_16:
|
|
instructions.add(new Goto(instLoc, ((Instruction20t)inst).getCodeOffset(), inst.getOpcode(), this));
|
|
break;
|
|
case GOTO_32:
|
|
instructions.add(new Goto(instLoc, ((Instruction30t)inst).getCodeOffset(), inst.getOpcode(), this));
|
|
break;
|
|
|
|
case PACKED_SWITCH:
|
|
case SPARSE_SWITCH:
|
|
instructions.add(new Switch(instLoc, ((Instruction31t)inst).getRegisterA(), ((Instruction31t)inst).getCodeOffset(), inst.getOpcode(), this));
|
|
break;
|
|
|
|
case CMPL_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.CMPL_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case CMPG_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.CMPG_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case CMPL_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.CMPL_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case CMPG_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.CMPG_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case CMP_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.CMPL_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_EQ:
|
|
instructions.add(new Branch.BinaryBranch(instLoc, ((Instruction22t)inst).getCodeOffset(),
|
|
Branch.BinaryBranch.CompareOp.EQ, ((Instruction22t)inst).getRegisterA(),
|
|
((Instruction22t)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_NE:
|
|
instructions.add(new Branch.BinaryBranch(instLoc, ((Instruction22t)inst).getCodeOffset(),
|
|
Branch.BinaryBranch.CompareOp.NE, ((Instruction22t)inst).getRegisterA(),
|
|
((Instruction22t)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_LT:
|
|
instructions.add(new Branch.BinaryBranch(instLoc, ((Instruction22t)inst).getCodeOffset(),
|
|
Branch.BinaryBranch.CompareOp.LT, ((Instruction22t)inst).getRegisterA(),
|
|
((Instruction22t)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_GE:
|
|
instructions.add(new Branch.BinaryBranch(instLoc, ((Instruction22t)inst).getCodeOffset(),
|
|
Branch.BinaryBranch.CompareOp.GE, ((Instruction22t)inst).getRegisterA(),
|
|
((Instruction22t)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_GT:
|
|
instructions.add(new Branch.BinaryBranch(instLoc, ((Instruction22t)inst).getCodeOffset(),
|
|
Branch.BinaryBranch.CompareOp.GT, ((Instruction22t)inst).getRegisterA(),
|
|
((Instruction22t)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_LE:
|
|
instructions.add(new Branch.BinaryBranch(instLoc, ((Instruction22t)inst).getCodeOffset(),
|
|
Branch.BinaryBranch.CompareOp.LE, ((Instruction22t)inst).getRegisterA(),
|
|
((Instruction22t)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_EQZ:
|
|
instructions.add(new Branch.UnaryBranch(instLoc,
|
|
((Instruction21t)inst).getCodeOffset(), Branch.UnaryBranch.CompareOp.EQZ,
|
|
((Instruction21t)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_NEZ:
|
|
instructions.add(new Branch.UnaryBranch(instLoc,
|
|
((Instruction21t)inst).getCodeOffset(), Branch.UnaryBranch.CompareOp.NEZ,
|
|
((Instruction21t)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_LTZ:
|
|
instructions.add(new Branch.UnaryBranch(instLoc,
|
|
((Instruction21t)inst).getCodeOffset(), Branch.UnaryBranch.CompareOp.LTZ,
|
|
((Instruction21t)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_GEZ:
|
|
instructions.add(new Branch.UnaryBranch(instLoc,
|
|
((Instruction21t)inst).getCodeOffset(), Branch.UnaryBranch.CompareOp.GEZ,
|
|
((Instruction21t)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_GTZ:
|
|
instructions.add(new Branch.UnaryBranch(instLoc,
|
|
((Instruction21t)inst).getCodeOffset(), Branch.UnaryBranch.CompareOp.GTZ,
|
|
((Instruction21t)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case IF_LEZ:
|
|
instructions.add(new Branch.UnaryBranch(instLoc,
|
|
((Instruction21t)inst).getCodeOffset(), Branch.UnaryBranch.CompareOp.LEZ,
|
|
((Instruction21t)inst).getRegisterA(), inst.getOpcode(), this));
|
|
break;
|
|
case AGET:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_int, inst.getOpcode(), this));
|
|
break;
|
|
case AGET_WIDE:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_wide, inst.getOpcode(), this));
|
|
break;
|
|
case AGET_OBJECT:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_object, inst.getOpcode(), this));
|
|
break;
|
|
case AGET_BOOLEAN:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_boolean, inst.getOpcode(), this));
|
|
break;
|
|
case AGET_BYTE:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_byte, inst.getOpcode(), this));
|
|
break;
|
|
case AGET_CHAR:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_char, inst.getOpcode(), this));
|
|
break;
|
|
case AGET_SHORT:
|
|
instructions.add(new ArrayGet(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_short, inst.getOpcode(), this));
|
|
break;
|
|
case APUT:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_int, inst.getOpcode(), this));
|
|
break;
|
|
case APUT_WIDE:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_wide, inst.getOpcode(), this));
|
|
break;
|
|
case APUT_OBJECT:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_object, inst.getOpcode(), this));
|
|
break;
|
|
case APUT_BOOLEAN:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_boolean, inst.getOpcode(), this));
|
|
break;
|
|
case APUT_BYTE:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_byte, inst.getOpcode(), this));
|
|
break;
|
|
case APUT_CHAR:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_char, inst.getOpcode(), this));
|
|
break;
|
|
case APUT_SHORT:
|
|
instructions.add(new ArrayPut(instLoc, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(), ((Instruction23x)inst).getRegisterC(), Type.t_short, inst.getOpcode(), this));
|
|
break;
|
|
case IGET:
|
|
case IGET_WIDE:
|
|
case IGET_OBJECT:
|
|
case IGET_BOOLEAN:
|
|
case IGET_BYTE:
|
|
case IGET_CHAR:
|
|
case IGET_SHORT: {
|
|
String cname = ((FieldReference)((Instruction22c)inst).getReference()).getDefiningClass();
|
|
String fname = ((FieldReference)((Instruction22c)inst).getReference()).getName();
|
|
String ftname = ((FieldReference)((Instruction22c)inst).getReference()).getType();
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
if (fname.endsWith(";"))
|
|
fname = fname.substring(0,fname.length()-1);
|
|
if (ftname.endsWith(";"))
|
|
ftname = ftname.substring(0,ftname.length()-1);
|
|
|
|
instructions.add(new GetField.GetInstanceField(
|
|
instLoc, ((Instruction22c)inst).getRegisterA(), ((Instruction22c)inst).getRegisterB(),
|
|
cname, fname, ftname, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case IPUT:
|
|
case IPUT_WIDE:
|
|
case IPUT_OBJECT:
|
|
case IPUT_BOOLEAN:
|
|
case IPUT_BYTE:
|
|
case IPUT_CHAR:
|
|
case IPUT_SHORT: {
|
|
String cname = ((FieldReference)((Instruction22c)inst).getReference()).getDefiningClass();
|
|
String fname = ((FieldReference)((Instruction22c)inst).getReference()).getName();
|
|
String ftname = ((FieldReference)((Instruction22c)inst).getReference()).getType();
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
if (fname.endsWith(";"))
|
|
fname = fname.substring(0,fname.length()-1);
|
|
if (ftname.endsWith(";"))
|
|
ftname = ftname.substring(0,ftname.length()-1);
|
|
|
|
instructions.add(new PutField.PutInstanceField(
|
|
instLoc, ((TwoRegisterInstruction)inst).getRegisterA(), ((TwoRegisterInstruction)inst).getRegisterB(),
|
|
cname, fname, ftname, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case SGET:
|
|
case SGET_WIDE:
|
|
case SGET_OBJECT:
|
|
case SGET_BOOLEAN:
|
|
case SGET_BYTE:
|
|
case SGET_CHAR:
|
|
case SGET_SHORT: {
|
|
String cname = ((FieldReference)((Instruction21c)inst).getReference()).getDefiningClass();
|
|
String fname = ((FieldReference)((Instruction21c)inst).getReference()).getName();
|
|
String ftname = ((FieldReference)((Instruction21c)inst).getReference()).getType();
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
if (fname.endsWith(";"))
|
|
fname = fname.substring(0,fname.length()-1);
|
|
if (ftname.endsWith(";"))
|
|
ftname = ftname.substring(0,ftname.length()-1);
|
|
|
|
instructions.add(new GetField.GetStaticField(instLoc,
|
|
((Instruction21c)inst).getRegisterA(), cname, fname, ftname, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case SPUT:
|
|
case SPUT_WIDE:
|
|
case SPUT_OBJECT:
|
|
case SPUT_BOOLEAN:
|
|
case SPUT_BYTE:
|
|
case SPUT_CHAR:
|
|
case SPUT_SHORT: {
|
|
String cname = ((FieldReference)((Instruction21c)inst).getReference()).getDefiningClass();
|
|
String fname = ((FieldReference)((Instruction21c)inst).getReference()).getName();
|
|
String ftname = ((FieldReference)((Instruction21c)inst).getReference()).getType();
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
if (fname.endsWith(";"))
|
|
fname = fname.substring(0,fname.length()-1);
|
|
if (ftname.endsWith(";"))
|
|
ftname = ftname.substring(0,ftname.length()-1);
|
|
|
|
instructions.add(new PutField.PutStaticField(instLoc,
|
|
((Instruction21c)inst).getRegisterA(), cname, fname, ftname, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INVOKE_VIRTUAL: {
|
|
int registerCount = ((Instruction35c)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
{
|
|
switch(i) {
|
|
case 0:
|
|
args[0] = ((Instruction35c)inst).getRegisterC();
|
|
break;
|
|
case 1:
|
|
args[1] = ((Instruction35c)inst).getRegisterD();
|
|
break;
|
|
case 2:
|
|
args[2] = ((Instruction35c)inst).getRegisterE();
|
|
break;
|
|
case 3:
|
|
args[3] = ((Instruction35c)inst).getRegisterF();
|
|
break;
|
|
case 4:
|
|
args[4] = ((Instruction35c)inst).getRegisterG();
|
|
break;
|
|
default:
|
|
throw new RuntimeException("Illegal instruction at "
|
|
+ instLoc + ": bad register count");
|
|
}
|
|
}
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
// if (mname.endsWith(";"))
|
|
// mname = mname.substring(0,mname.length()-1);
|
|
// if (pname.endsWith(";"))
|
|
// pname = pname.substring(0,pname.length()-1);
|
|
|
|
// for (IMethod m: this.myClass.loader.lookupClass(TypeName.findOrCreate(cname)).getDeclaredMethods())
|
|
// System.out.println(m.getDescriptor().toString());
|
|
|
|
handleINVOKE_VIRTUAL(instLoc, cname, mname, pname, args, inst.getOpcode());
|
|
//instructions.add(new Invoke.InvokeVirtual(instLoc, cname, mname, pname, args, inst.opcode, this));
|
|
//logger.debug("\t" + inst.opcode.toString() + " class: "+ cname + ", method name: " + mname + ", prototype string: " + pname);
|
|
|
|
break;
|
|
}
|
|
case INVOKE_SUPER: {
|
|
int registerCount = ((Instruction35c)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
{
|
|
switch(i) {
|
|
case 0:
|
|
args[0] = ((Instruction35c)inst).getRegisterC();
|
|
break;
|
|
case 1:
|
|
args[1] = ((Instruction35c)inst).getRegisterD();
|
|
break;
|
|
case 2:
|
|
args[2] = ((Instruction35c)inst).getRegisterE();
|
|
break;
|
|
case 3:
|
|
args[3] = ((Instruction35c)inst).getRegisterF();
|
|
break;
|
|
case 4:
|
|
args[4] = ((Instruction35c)inst).getRegisterG();
|
|
break;
|
|
default:
|
|
throw new RuntimeException("Illegal instruction at "
|
|
+ instLoc + ": bad register count");
|
|
}
|
|
}
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
instructions.add(new Invoke.InvokeSuper(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INVOKE_DIRECT: {
|
|
int registerCount = ((Instruction35c)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
{
|
|
switch(i) {
|
|
case 0:
|
|
args[0] = ((Instruction35c)inst).getRegisterC();
|
|
break;
|
|
case 1:
|
|
args[1] = ((Instruction35c)inst).getRegisterD();
|
|
break;
|
|
case 2:
|
|
args[2] = ((Instruction35c)inst).getRegisterE();
|
|
break;
|
|
case 3:
|
|
args[3] = ((Instruction35c)inst).getRegisterF();
|
|
break;
|
|
case 4:
|
|
args[4] = ((Instruction35c)inst).getRegisterG();
|
|
break;
|
|
default:
|
|
throw new RuntimeException("Illegal instruction at "
|
|
+ instLoc + ": bad register count");
|
|
}
|
|
}
|
|
|
|
// logger.debug(inst.opcode.toString() + " class: "+((MethodIdItem)((Instruction35c)inst).getReferencedItem()).getContainingClass().getTypeDescriptor() + ", method name: " + ((MethodIdItem)((Instruction35c)inst).getReferencedItem()).getMethodName().getStringValue() + ", prototype string: " + ((MethodIdItem)((Instruction35c)inst).getReferencedItem()).getPrototype().getPrototypeString());
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
instructions.add(new Invoke.InvokeDirect(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
|
|
break;
|
|
}
|
|
case INVOKE_STATIC: {
|
|
int registerCount = ((Instruction35c)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
{
|
|
switch(i) {
|
|
case 0:
|
|
args[0] = ((Instruction35c)inst).getRegisterC();
|
|
break;
|
|
case 1:
|
|
args[1] = ((Instruction35c)inst).getRegisterD();
|
|
break;
|
|
case 2:
|
|
args[2] = ((Instruction35c)inst).getRegisterE();
|
|
break;
|
|
case 3:
|
|
args[3] = ((Instruction35c)inst).getRegisterF();
|
|
break;
|
|
case 4:
|
|
args[4] = ((Instruction35c)inst).getRegisterG();
|
|
break;
|
|
default:
|
|
throw new RuntimeException("Illegal instruction at "
|
|
+ instLoc + ": bad register count");
|
|
}
|
|
}
|
|
|
|
//logger.debug(inst.opcode.toString() + " class: "+((MethodIdItem)((Instruction35c)inst).getReferencedItem()).getContainingClass().getTypeDescriptor() + ", method name: " + ((MethodIdItem)((Instruction35c)inst).getReferencedItem()).getMethodName().getStringValue() + ", prototype string: " + ((MethodIdItem)((Instruction35c)inst).getReferencedItem()).getPrototype().getPrototypeString());
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
|
|
instructions.add(new Invoke.InvokeStatic(instLoc, cname, mname, pname, args, inst.getOpcode(), this));
|
|
|
|
break;
|
|
}
|
|
case INVOKE_INTERFACE: {
|
|
int registerCount = ((Instruction35c)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
{
|
|
switch(i) {
|
|
case 0:
|
|
args[0] = ((Instruction35c)inst).getRegisterC();
|
|
break;
|
|
case 1:
|
|
args[1] = ((Instruction35c)inst).getRegisterD();
|
|
break;
|
|
case 2:
|
|
args[2] = ((Instruction35c)inst).getRegisterE();
|
|
break;
|
|
case 3:
|
|
args[3] = ((Instruction35c)inst).getRegisterF();
|
|
break;
|
|
case 4:
|
|
args[4] = ((Instruction35c)inst).getRegisterG();
|
|
break;
|
|
default:
|
|
throw new RuntimeException("Illegal instruction at "
|
|
+ instLoc + ": bad register count");
|
|
}
|
|
}
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction35c)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
instructions.add(new Invoke.InvokeInterface(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INVOKE_VIRTUAL_RANGE: {
|
|
int registerCount = ((Instruction3rc)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
args[i] = ((Instruction3rc)inst).getStartRegister() + i;
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
instructions.add(new Invoke.InvokeVirtual(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INVOKE_SUPER_RANGE: {
|
|
int registerCount = ((Instruction3rc)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
args[i] = ((Instruction3rc)inst).getStartRegister() + i;
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
instructions.add(new Invoke.InvokeSuper(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INVOKE_DIRECT_RANGE: {
|
|
int registerCount = ((Instruction3rc)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
args[i] = ((Instruction3rc)inst).getStartRegister() + i;
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
instructions.add(new Invoke.InvokeDirect(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case INVOKE_STATIC_RANGE: {
|
|
int registerCount = ((Instruction3rc)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
args[i] = ((Instruction3rc)inst).getStartRegister() + i;
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
|
|
instructions.add(new Invoke.InvokeStatic(instLoc, cname, mname, pname, args, inst.getOpcode(), this));
|
|
|
|
break;
|
|
}
|
|
case INVOKE_INTERFACE_RANGE: {
|
|
int registerCount = ((Instruction3rc)inst).getRegisterCount();
|
|
int[] args = new int[registerCount];
|
|
|
|
for (int i = 0; i < registerCount; i++)
|
|
args[i] = ((Instruction3rc)inst).getStartRegister() + i;
|
|
|
|
String cname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getDefiningClass();
|
|
String mname = ((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference()).getName();
|
|
String pname = DexUtil.getSignature((org.jf.dexlib2.iface.reference.MethodReference)((Instruction3rc)inst).getReference());
|
|
|
|
if (cname.endsWith(";"))
|
|
cname = cname.substring(0,cname.length()-1);
|
|
|
|
instructions.add(new Invoke.InvokeInterface(instLoc,
|
|
cname, mname, pname, args, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case NEG_INT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.NEGINT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case NOT_INT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.NOTINT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case NEG_LONG:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.NEGLONG, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case NOT_LONG:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.NOTLONG, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case NEG_FLOAT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.NEGFLOAT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case NEG_DOUBLE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.NEGDOUBLE, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case INT_TO_LONG:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.INTTOLONG, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case INT_TO_FLOAT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.INTTOFLOAT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case INT_TO_DOUBLE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.INTTODOUBLE, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case LONG_TO_INT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.LONGTOINT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case LONG_TO_FLOAT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.LONGTOFLOAT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case LONG_TO_DOUBLE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.LONGTODOUBLE, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case FLOAT_TO_INT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.FLOATTOINT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case FLOAT_TO_LONG:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.FLOATTOLONG, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case FLOAT_TO_DOUBLE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.FLOATTODOUBLE, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DOUBLE_TO_INT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.DOUBLETOINT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DOUBLE_TO_LONG:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.DOUBLETOLONG, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DOUBLE_TO_FLOAT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.DOUBLETOFLOAT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case INT_TO_BYTE:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.INTTOBYTE, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case INT_TO_CHAR:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.INTTOCHAR, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case INT_TO_SHORT:
|
|
instructions.add(new UnaryOperation(instLoc,
|
|
OpID.INTTOSHORT, ((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case AND_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.AND_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case OR_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.OR_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case XOR_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.XOR_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SHL_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHL_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SHR_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHR_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case USHR_INT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.USHR_INT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case AND_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.AND_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case OR_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.OR_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case XOR_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.XOR_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SHL_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHL_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SHR_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHR_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case USHR_LONG:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.USHR_LONG, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_FLOAT:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_FLOAT, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_DOUBLE:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_DOUBLE, ((Instruction23x)inst).getRegisterA(),
|
|
((Instruction23x)inst).getRegisterB(),((Instruction23x)inst).getRegisterC(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case AND_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.AND_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case OR_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.OR_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case XOR_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.XOR_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SHL_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHL_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SHR_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHR_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case USHR_INT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.USHR_INT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case AND_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.AND_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case OR_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.OR_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case XOR_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.XOR_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SHL_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHL_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SHR_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SHR_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case USHR_LONG_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.USHR_LONG, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_FLOAT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_FLOAT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_FLOAT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_FLOAT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_FLOAT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_FLOAT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_FLOAT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_FLOAT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_FLOAT_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_FLOAT, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_DOUBLE_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.ADD_DOUBLE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case SUB_DOUBLE_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.SUB_DOUBLE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case MUL_DOUBLE_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.MUL_DOUBLE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case DIV_DOUBLE_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.DIV_DOUBLE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case REM_DOUBLE_2ADDR:
|
|
instructions.add(new BinaryOperation(instLoc,
|
|
BinaryOperation.OpID.REM_DOUBLE, ((Instruction12x)inst).getRegisterA(),
|
|
((Instruction12x)inst).getRegisterA(), ((Instruction12x)inst).getRegisterB(), inst.getOpcode(), this));
|
|
break;
|
|
case ADD_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.ADD_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case RSUB_INT: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.RSUB_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case MUL_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.MUL_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case DIV_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.DIV_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case REM_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.REM_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case AND_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.AND_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case OR_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.OR_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case XOR_INT_LIT16: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22s)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.XOR_INT,
|
|
((Instruction22s)inst).getRegisterA(), ((Instruction22s)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case ADD_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.ADD_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case RSUB_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.RSUB_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case MUL_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.MUL_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case DIV_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.DIV_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case REM_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.REM_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case AND_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.AND_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case OR_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.OR_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case XOR_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.XOR_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case SHL_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.SHL_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case SHR_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.SHR_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
case USHR_INT_LIT8: {
|
|
Literal lit = new Literal.LongLiteral(((Instruction22b)inst).getWideLiteral());
|
|
instructions.add(new BinaryLiteralOperation(instLoc, BinaryLiteralOperation.OpID.USHR_INT,
|
|
((Instruction22b)inst).getRegisterA(), ((Instruction22b)inst).getRegisterB(), lit, inst.getOpcode(), this));
|
|
break;
|
|
}
|
|
default:
|
|
throw new RuntimeException("not implemented instruction: 0x"
|
|
+ inst.getOpcode().toString() + " in " + eMethod.getDefiningClass() + ":" + eMethod.getName());
|
|
|
|
}
|
|
currentCodeAddress += inst.getCodeUnits();
|
|
}
|
|
|
|
//// comment out start
|
|
//// Instruction[] iinstructions = new Instruction[instrucs.length];
|
|
// instructions = new InsructionArray();
|
|
//
|
|
//
|
|
// for (int i = 0; i < instrucs.length; i++) {
|
|
// org.jf.dexlib.Code.Instruction instruction = instrucs[i];
|
|
//
|
|
//
|
|
// System.out.println(instruction.toString());
|
|
// switch (instruction.getFormat()) {
|
|
//
|
|
// /*
|
|
//- 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),
|
|
// 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),
|
|
// Format35ms(Instruction35ms.Factory, 6),
|
|
// Format3rc(Instruction3rc.Factory, 6),
|
|
// Format3rms(Instruction3rms.Factory, 6),
|
|
// Format51l(Instruction51l.Factory, 10),
|
|
// ArrayData(null, -1, true),
|
|
// PackedSwitchData(null, -1, true),
|
|
// SparseSwitchData(null, -1, true),
|
|
// UnresolvedOdexInstruction(null, -1, false),
|
|
//*/
|
|
// case Format10t: { //goto
|
|
//
|
|
//
|
|
// Instruction10t dInst = (Instruction10t)instruction;
|
|
//
|
|
// int offset = dInst.getCodeOffset();
|
|
// instructions.add(new Goto(i,offset));
|
|
//
|
|
// break;
|
|
// }
|
|
// case Format10x: {
|
|
//
|
|
// switch(instruction.opcode) {
|
|
// case RETURN_VOID: {
|
|
// instructions.add(new Return.ReturnVoid(i));
|
|
// break;
|
|
// }
|
|
// default:
|
|
// break;
|
|
// }
|
|
//
|
|
// break;
|
|
// }
|
|
//
|
|
// case Format11n: {
|
|
//
|
|
// Instruction11n dInst = (Instruction11n) instruction;
|
|
//
|
|
// System.out.println("here1");
|
|
// int a = (int)dInst.getLiteral();
|
|
// System.out.println("here2");
|
|
// Register b = regBank.get(dInst.getRegisterA());
|
|
// System.out.println("here3");
|
|
//
|
|
// Constant.IntConstant c = new Constant.IntConstant(1, 2, b);
|
|
// //instructions.add(c);
|
|
// System.out.println("here5");
|
|
// instructions.add(new Constant.IntConstant(i,
|
|
// (int)dInst.getLiteral(), regBank.get(dInst.getRegisterA())));
|
|
// System.out.println("here4");
|
|
// break;
|
|
// }
|
|
//
|
|
// case Format11x: {
|
|
// /*
|
|
// * MOVE_RESULT((byte)0x0a, "move-result", ReferenceType.none, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// MOVE_RESULT_WIDE((byte)0x0b, "move-result-wide", ReferenceType.none, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// MOVE_RESULT_OBJECT((byte)0x0c, "move-result-object", ReferenceType.none, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// MOVE_EXCEPTION((byte)0x0d, "move-exception", ReferenceType.none, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// 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),
|
|
// MONITOR_ENTER((byte)0x1d, "monitor-enter", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// MONITOR_EXIT((byte)0x1e, "monitor-exit", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// THROW((byte)0x27, "throw", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW),
|
|
// */
|
|
//
|
|
// Instruction11x dInst = (Instruction11x) instruction;
|
|
//
|
|
// switch (dInst.opcode) {
|
|
// case MOVE_RESULT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE, regBank.get(dInst.getRegisterA()),
|
|
// regBank.getReturnReg()));
|
|
// break;
|
|
// }
|
|
// case MOVE_RESULT_WIDE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE_WIDE,
|
|
// regBank.get(dInst.getRegisterA()), regBank.getReturnReg()));
|
|
// break;
|
|
// }
|
|
// case MOVE_RESULT_OBJECT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE, regBank.get(dInst.getRegisterA()),
|
|
// regBank.getReturnReg()));
|
|
// break;
|
|
// }
|
|
// case MOVE_EXCEPTION: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE, regBank.get(dInst.getRegisterA()),
|
|
// regBank.getReturnExceptionReg()));
|
|
// break;
|
|
// }
|
|
// case RETURN: {
|
|
// instructions.add(new Return.ReturnSingle(i,
|
|
// regBank.get(dInst.getRegisterA())));
|
|
// break;
|
|
// }
|
|
// case RETURN_WIDE: {
|
|
// instructions.add(new Return.ReturnDouble(i,
|
|
// regBank.get(dInst.getRegisterA()), regBank.get(dInst.getRegisterA() + 1)));
|
|
// break;
|
|
// }
|
|
// case RETURN_OBJECT: {
|
|
// instructions.add(new Return.ReturnSingle(i,
|
|
// regBank.get(dInst.getRegisterA())));
|
|
// break;
|
|
// }
|
|
// case MONITOR_ENTER: {
|
|
// instructions.add(new Monitor(i, true, regBank
|
|
// .get(dInst.getRegisterA())));
|
|
// break;
|
|
// }
|
|
// case MONITOR_EXIT: {
|
|
// instructions.add(new Monitor(i, false, regBank
|
|
// .get(dInst.getRegisterA())));
|
|
// break;
|
|
// }
|
|
// case THROW: {
|
|
// instructions.add(new Throw(i, regBank
|
|
// .get(dInst.getRegisterA())));
|
|
// break;
|
|
// }
|
|
// default:
|
|
// break;
|
|
// }
|
|
// break;
|
|
// }
|
|
//
|
|
// case Format12x: {
|
|
//
|
|
// Instruction12x dInst = (Instruction12x) instruction;
|
|
// int destination = dInst.getRegisterA();
|
|
// int source = dInst.getRegisterB();
|
|
//
|
|
// switch(dInst.opcode) {
|
|
// // MOVE((byte)0x01, "move", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case MOVE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE, regBank.get(destination),
|
|
// regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // MOVE_WIDE((byte)0x04, "move-wide", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case MOVE_WIDE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE_WIDE,
|
|
// regBank.get(destination), regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // MOVE_OBJECT((byte)0x07, "move-object", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case MOVE_OBJECT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// UnaryOperation.OpID.MOVE, regBank.get(destination),
|
|
// regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // ARRAY_LENGTH((byte)0x21, "array-length", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case ARRAY_LENGTH: {
|
|
// instructions.add(new ArrayLength(i, regBank
|
|
// .get(destination), regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // NEG_INT((byte)0x7b, "neg-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case NEG_INT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.NEGINT, regBank.get(destination), regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // NOT_INT((byte)0x7c, "not-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case NOT_INT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.NOTINT, regBank.get(destination), regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // NEG_LONG((byte)0x7d, "neg-long", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case NEG_LONG: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.NEGLONG, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // NOT_LONG((byte)0x7e, "not-long", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case NOT_LONG: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.NOTLONG, regBank.get(destination), regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // NEG_FLOAT((byte)0x7f, "neg-float", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case NEG_FLOAT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.NEGFLOAT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
//
|
|
// }
|
|
// // NEG_DOUBLE((byte)0x80, "neg-double", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case NEG_DOUBLE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.NEGDOUBLE, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // INT_TO_LONG((byte)0x81, "int-to-long", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case INT_TO_LONG: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.INTTOLONG, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // INT_TO_FLOAT((byte)0x82, "int-to-float", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case INT_TO_FLOAT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.INTTOFLOAT, regBank.get(destination), regBank.get(source)));
|
|
// break;
|
|
// }
|
|
// // INT_TO_DOUBLE((byte)0x83, "int-to-double", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case INT_TO_DOUBLE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.INTTODOUBLE, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // LONG_TO_INT((byte)0x84, "long-to-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case LONG_TO_INT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.LONGTOINT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // LONG_TO_FLOAT((byte)0x85, "long-to-float", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case LONG_TO_FLOAT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.LONGTOFLOAT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // LONG_TO_DOUBLE((byte)0x86, "long-to-double", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case LONG_TO_DOUBLE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.LONGTODOUBLE, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // FLOAT_TO_INT((byte)0x87, "float-to-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case FLOAT_TO_INT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.FLOATTOINT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // FLOAT_TO_LONG((byte)0x88, "float-to-long", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case FLOAT_TO_LONG: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.FLOATTOLONG, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // FLOAT_TO_DOUBLE((byte)0x89, "float-to-double", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case FLOAT_TO_DOUBLE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.FLOATTODOUBLE, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // DOUBLE_TO_INT((byte)0x8a, "double-to-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case DOUBLE_TO_INT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.DOUBLETOINT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // DOUBLE_TO_LONG((byte)0x8b, "double-to-long", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case DOUBLE_TO_LONG: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.DOUBLETOLONG, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // DOUBLE_TO_FLOAT((byte)0x8c, "double-to-float", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case DOUBLE_TO_FLOAT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.DOUBLETOFLOAT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // INT_TO_BYTE((byte)0x8d, "int-to-byte", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case INT_TO_BYTE: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.INTTOBYTE, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // INT_TO_CHAR((byte)0x8e, "int-to-char", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case INT_TO_CHAR: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.INTTOCHAR, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // INT_TO_SHORT((byte)0x8f, "int-to-short", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case INT_TO_SHORT: {
|
|
// instructions.add(new UnaryOperation(i,
|
|
// OpID.INTTOSHORT, regBank.get(destination), regBank.get(source)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // ADD_INT_2ADDR((byte)0xb0, "add-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case ADD_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.ADD_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SUB_INT_2ADDR((byte)0xb1, "sub-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SUB_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SUB_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // MUL_INT_2ADDR((byte)0xb2, "mul-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case MUL_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.MUL_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // DIV_INT_2ADDR((byte)0xb3, "div-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case DIV_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.DIV_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // REM_INT_2ADDR((byte)0xb4, "rem-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case REM_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.REM_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // AND_INT_2ADDR((byte)0xb5, "and-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case AND_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.AND_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // OR_INT_2ADDR((byte)0xb6, "or-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case OR_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.OR_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // XOR_INT_2ADDR((byte)0xb7, "xor-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case XOR_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.XOR_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SHL_INT_2ADDR((byte)0xb8, "shl-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SHL_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SHL_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SHR_INT_2ADDR((byte)0xb9, "shr-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SHR_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SHR_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // USHR_INT_2ADDR((byte)0xba, "ushr-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case USHR_INT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.USHR_INT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // ADD_LONG_2ADDR((byte)0xbb, "add-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case ADD_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.ADD_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SUB_LONG_2ADDR((byte)0xbc, "sub-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case SUB_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SUB_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // MUL_LONG_2ADDR((byte)0xbd, "mul-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case MUL_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.MUL_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // DIV_LONG_2ADDR((byte)0xbe, "div-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case DIV_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.DIV_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // REM_LONG_2ADDR((byte)0xbf, "rem-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case REM_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.REM_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // AND_LONG_2ADDR((byte)0xc0, "and-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case AND_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.AND_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // OR_LONG_2ADDR((byte)0xc1, "or-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case OR_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.OR_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // XOR_LONG_2ADDR((byte)0xc2, "xor-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case XOR_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.XOR_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SHL_LONG_2ADDR((byte)0xc3, "shl-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case SHL_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SHL_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SHR_LONG_2ADDR((byte)0xc4, "shr-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case SHR_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SHR_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // USHR_LONG_2ADDR((byte)0xc5, "ushr-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case USHR_LONG_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.USHR_LONG, d, d, s));
|
|
// break;
|
|
// }
|
|
// // ADD_FLOAT_2ADDR((byte)0xc6, "add-float/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case ADD_FLOAT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.ADD_FLOAT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SUB_FLOAT_2ADDR((byte)0xc7, "sub-float/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SUB_FLOAT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SUB_FLOAT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // MUL_FLOAT_2ADDR((byte)0xc8, "mul-float/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case MUL_FLOAT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.MUL_FLOAT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // DIV_FLOAT_2ADDR((byte)0xc9, "div-float/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case DIV_FLOAT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.DIV_FLOAT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // REM_FLOAT_2ADDR((byte)0xca, "rem-float/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case REM_FLOAT_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.REM_FLOAT, d, d, s));
|
|
// break;
|
|
// }
|
|
// // ADD_DOUBLE_2ADDR((byte)0xcb, "add-double/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case ADD_DOUBLE_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.ADD_DOUBLE, d, d, s));
|
|
// break;
|
|
// }
|
|
// // SUB_DOUBLE_2ADDR((byte)0xcc, "sub-double/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case SUB_DOUBLE_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.SUB_DOUBLE, d, d, s));
|
|
// break;
|
|
// }
|
|
// // MUL_DOUBLE_2ADDR((byte)0xcd, "mul-double/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case MUL_DOUBLE_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.MUL_DOUBLE, d, d, s));
|
|
// break;
|
|
// }
|
|
// // DIV_DOUBLE_2ADDR((byte)0xce, "div-double/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case DIV_DOUBLE_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.DIV_DOUBLE, d, d, s));
|
|
// break;
|
|
// }
|
|
// // REM_DOUBLE_2ADDR((byte)0xcf, "rem-double/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case REM_DOUBLE_2ADDR: {
|
|
// Register d = regBank.get(destination);
|
|
// Register s = regBank.get(source);
|
|
// instructions.add(new BinaryOperation(i,
|
|
// BinaryOperation.OpID.REM_DOUBLE, d, d, s));
|
|
// break;
|
|
// }
|
|
// default:
|
|
// break;
|
|
// }
|
|
//
|
|
// break;
|
|
// }
|
|
//
|
|
// case Format20t: { //goto/16
|
|
//
|
|
//
|
|
// Instruction20t dInst = (Instruction20t)instruction;
|
|
//
|
|
// int offset = dInst.getCodeOffset();
|
|
// instructions.add(new Goto(i,offset));
|
|
// break;
|
|
// }
|
|
// case Format30t: { //goto/32
|
|
//
|
|
//
|
|
// Instruction30t dInst = (Instruction30t)instruction;
|
|
//
|
|
// int offset = dInst.getCodeOffset();
|
|
// instructions.add(new Goto(i,offset));
|
|
// break;
|
|
// }
|
|
//
|
|
// case Format21c: {
|
|
// Instruction21c dInst = (Instruction21c) instruction;
|
|
//
|
|
//
|
|
// switch (dInst.opcode) {
|
|
// //CONST_STRING((byte)0x1a, "const-string", ReferenceType.string, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case CONST_STRING: {
|
|
// int destination = dInst.getRegisterA();
|
|
// instructions.add(new Constant.StringConstant(i,
|
|
// dInst.getReferencedItem().getConciseIdentity(), regBank.get(destination)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // CONST_CLASS((byte)0x1c, "const-class", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case CONST_CLASS: {
|
|
// int destination = dInst.getRegisterA();
|
|
// IClass value = this.myClass.getClassLoader().lookupClass(TypeName.findOrCreate(dInst.getReferencedItem().getConciseIdentity()));
|
|
//
|
|
// instructions.add(new Constant.ClassConstant(i,
|
|
// value, regBank.get(destination)));
|
|
// break;
|
|
// }
|
|
// // CHECK_CAST((byte)0x1f, "check-cast", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case CHECK_CAST: {
|
|
// int val = dInst.getRegisterA();
|
|
// String type = dInst.getReferencedItem().getConciseIdentity();
|
|
// instructions.add(new CheckCast(i, TypeReference
|
|
// .findOrCreate(this.myClass.getClassLoader().getReference(), type), regBank
|
|
// .get(val)));
|
|
//
|
|
// break;
|
|
// }
|
|
// // NEW_INSTANCE((byte)0x22, "new-instance", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case NEW_INSTANCE: {
|
|
// int destination = dInst.getRegisterA();
|
|
// String type = dInst.getReferencedItem().getConciseIdentity();
|
|
// instructions.add(new New(i, regBank
|
|
// .get(destination), NewSiteReference.make(i,
|
|
// TypeReference
|
|
// .findOrCreate(this.myClass.getClassLoader().getReference(), type))));
|
|
// break;
|
|
// }
|
|
// // SGET((byte)0x60, "sget", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SGET:
|
|
// // SGET_WIDE((byte)0x61, "sget-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// case SGET_WIDE:
|
|
// // SGET_OBJECT((byte)0x62, "sget-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SGET_OBJECT:
|
|
// // SGET_BOOLEAN((byte)0x63, "sget-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SGET_BOOLEAN:
|
|
// // SGET_BYTE((byte)0x64, "sget-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SGET_BYTE:
|
|
// // SGET_CHAR((byte)0x65, "sget-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SGET_CHAR:
|
|
// // SGET_SHORT((byte)0x66, "sget-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// case SGET_SHORT: {
|
|
//
|
|
// /* TODO
|
|
// Register destination = regBank.get(dInst.getRegisterA());
|
|
// Register source = regBank.get(dInst.getReferencedItem().getOffset());
|
|
// int fieldIndex = codes[pc++];
|
|
// this.eMethod
|
|
// String clazzName = fieldClasses[fieldIndex];
|
|
// String fieldName = fieldNames[fieldIndex];
|
|
// String fieldType = fieldTypes[fieldIndex];
|
|
// // getField(false, frame, source, fieldIndex, destination);
|
|
// instructions.add(new GetField.GetInstanceField(
|
|
// instLoc, destination, source, clazzName, fieldName,
|
|
// fieldType));
|
|
//*/
|
|
// break;
|
|
// }
|
|
// // SPUT((byte)0x67, "sput", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SPUT_WIDE((byte)0x68, "sput-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SPUT_OBJECT((byte)0x69, "sput-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SPUT_BOOLEAN((byte)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SPUT_BYTE((byte)0x6b, "sput-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SPUT_CHAR((byte)0x6c, "sput-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SPUT_SHORT((byte)0x6d, "sput-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SGET_VOLATILE((byte)0xe5, "sget-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// // SPUT_VOLATILE((byte)0xe6, "sput-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SGET_WIDE_VOLATILE((byte)0xea, "sget-wide-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER),
|
|
// // SPUT_WIDE_VOLATILE((byte)0xeb, "sput-wide-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
|
// // SGET_OBJECT_VOLATILE((byte)0xfd, "sget-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
|
|
// // SPUT_OBJECT_VOLATILE((byte)0xfe, "sput-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE);
|
|
// default:
|
|
// break;
|
|
// }
|
|
// break;
|
|
// }
|
|
//
|
|
// case Format21t: {
|
|
//
|
|
// Instruction21t dInst = (Instruction21t)instruction;
|
|
//
|
|
// Register oper1 = regBank.get(dInst.getRegisterA());
|
|
// int offset = dInst.getCodeOffset();
|
|
//
|
|
// switch(dInst.opcode) {
|
|
// case IF_EQZ:
|
|
// instructions.add(new Branch.UnaryBranch(i,
|
|
// offset, Branch.UnaryBranch.CompareOp.EQZ, oper1));
|
|
// break;
|
|
// case IF_NEZ:
|
|
// instructions.add(new Branch.UnaryBranch(i,
|
|
// offset, Branch.UnaryBranch.CompareOp.NEZ, oper1));
|
|
// break;
|
|
// case IF_LTZ:
|
|
// instructions.add(new Branch.UnaryBranch(i,
|
|
// offset, Branch.UnaryBranch.CompareOp.LTZ, oper1));
|
|
// break;
|
|
// case IF_GEZ:
|
|
// instructions.add(new Branch.UnaryBranch(i,
|
|
// offset, Branch.UnaryBranch.CompareOp.GEZ, oper1));
|
|
// break;
|
|
// case IF_GTZ:
|
|
// instructions.add(new Branch.UnaryBranch(i,
|
|
// offset, Branch.UnaryBranch.CompareOp.GTZ, oper1));
|
|
// break;
|
|
// case IF_LEZ:
|
|
// instructions.add(new Branch.UnaryBranch(i,
|
|
// offset, Branch.UnaryBranch.CompareOp.LEZ, oper1));
|
|
// break;
|
|
// default:
|
|
// logger.debug(instruction.opcode.name + " - " + instruction.getFormat().toString());
|
|
// break;
|
|
// }
|
|
// /*
|
|
// IF_EQZ((byte)0x38, "if-eqz", ReferenceType.none, Format.Format21t, Opcode.CAN_CONTINUE),
|
|
// IF_NEZ((byte)0x39, "if-nez", ReferenceType.none, Format.Format21t, Opcode.CAN_CONTINUE),
|
|
// IF_LTZ((byte)0x3a, "if-ltz", ReferenceType.none, Format.Format21t, Opcode.CAN_CONTINUE),
|
|
// IF_GEZ((byte)0x3b, "if-gez", ReferenceType.none, Format.Format21t, Opcode.CAN_CONTINUE),
|
|
// IF_GTZ((byte)0x3c, "if-gtz", ReferenceType.none, Format.Format21t, Opcode.CAN_CONTINUE),
|
|
// IF_LEZ((byte)0x3d, "if-lez", ReferenceType.none, Format.Format21t, Opcode.CAN_CONTINUE),
|
|
//
|
|
// */
|
|
// break;
|
|
// }
|
|
// case Format22t: {
|
|
// Instruction22t dInst = (Instruction22t)instruction;
|
|
//
|
|
//
|
|
// Register oper1 = regBank.get(dInst.getRegisterA());
|
|
// Register oper2 = regBank.get(dInst.getRegisterB());
|
|
// int offset = dInst.getTargetAddressOffset();
|
|
//
|
|
// switch(dInst.opcode) {
|
|
// case IF_EQ:
|
|
// instructions.add(new Branch.BinaryBranch(i, offset,
|
|
// Branch.BinaryBranch.CompareOp.EQ, oper1, oper2));
|
|
// break;
|
|
// case IF_NE:
|
|
// instructions.add(new Branch.BinaryBranch(i, offset,
|
|
// Branch.BinaryBranch.CompareOp.NE, oper1, oper2));
|
|
// break;
|
|
// case IF_LT:
|
|
// instructions.add(new Branch.BinaryBranch(i, offset,
|
|
// Branch.BinaryBranch.CompareOp.LT, oper1, oper2));
|
|
// break;
|
|
// case IF_GE:
|
|
// instructions.add(new Branch.BinaryBranch(i, offset,
|
|
// Branch.BinaryBranch.CompareOp.GE, oper1, oper2));
|
|
// break;
|
|
// case IF_GT:
|
|
// instructions.add(new Branch.BinaryBranch(i, offset,
|
|
// Branch.BinaryBranch.CompareOp.GT, oper1, oper2));
|
|
// break;
|
|
// case IF_LE:
|
|
// instructions.add(new Branch.BinaryBranch(i, offset,
|
|
// Branch.BinaryBranch.CompareOp.LE, oper1, oper2));
|
|
// break;
|
|
// default:
|
|
// logger.debug(instruction.opcode.name + " - " + instruction.getFormat().toString());
|
|
// break;
|
|
// }
|
|
///* IF_EQ((byte)0x32, "if-eq", ReferenceType.none, Format.Format22t, Opcode.CAN_CONTINUE),
|
|
// IF_NE((byte)0x33, "if-ne", ReferenceType.none, Format.Format22t, Opcode.CAN_CONTINUE),
|
|
// IF_LT((byte)0x34, "if-lt", ReferenceType.none, Format.Format22t, Opcode.CAN_CONTINUE),
|
|
// IF_GE((byte)0x35, "if-ge", ReferenceType.none, Format.Format22t, Opcode.CAN_CONTINUE),
|
|
// IF_GT((byte)0x36, "if-gt", ReferenceType.none, Format.Format22t, Opcode.CAN_CONTINUE),
|
|
// IF_LE((byte)0x37, "if-le", ReferenceType.none, Format.Format22t, Opcode.CAN_CONTINUE),
|
|
//*/
|
|
// break;
|
|
// }
|
|
// case Format31t: {
|
|
// /* PACKED_SWITCH((byte)0x2b, "packed-switch", ReferenceType.none, Format.Format31t, Opcode.CAN_CONTINUE),
|
|
// SPARSE_SWITCH((byte)0x2c, "sparse-switch", ReferenceType.none, Format.Format31t, Opcode.CAN_CONTINUE),
|
|
//*/
|
|
// Instruction31t dInst = (Instruction31t)instruction;
|
|
// Register val = regBank.get(dInst.getRegisterA());
|
|
// int offset = dInst.getTargetAddressOffset();
|
|
// // instructions.add(new Switch(i,
|
|
// // getSparseSwitchPad(offset, codes, 3), val));
|
|
// break;
|
|
// }
|
|
//
|
|
//
|
|
//
|
|
// case Format35c: {
|
|
//
|
|
// // = invoke virtual
|
|
// //iinstructions[i] = new IInstruction35c((Instruction35c)instruction, this);
|
|
// break;
|
|
// }
|
|
//
|
|
//
|
|
// default:
|
|
// logger.debug(instruction.opcode.name + " - " + instruction.getFormat().toString());
|
|
// break;
|
|
// }
|
|
//
|
|
//
|
|
// }
|
|
//
|
|
// //comment out stop
|
|
}
|
|
|
|
private static TypeReference findOutArrayElementType(
|
|
org.jf.dexlib2.iface.instruction.Instruction inst, Instruction[] walaInstructions, int instCounter) {
|
|
if (instCounter < 0) {
|
|
throw new IllegalArgumentException();
|
|
} else if (instCounter == 0) {
|
|
throw new UnsupportedOperationException("fill-array-data as first instruction is not supported!");
|
|
}
|
|
|
|
Instruction31t arrayFill = (Instruction31t)inst;
|
|
int interestingRegister = arrayFill.getRegisterA();
|
|
int curCounter = instCounter - 1;
|
|
|
|
while (curCounter >= 0) {
|
|
Instruction curInst = walaInstructions[curCounter];
|
|
// do we have a 'new-array'-instruction, where the destination register coincides with the current interesting register?
|
|
// then we return the element type of that array
|
|
if (curInst.getOpcode() == Opcode.NEW_ARRAY) {
|
|
NewArray newArray = (NewArray) walaInstructions[curCounter];
|
|
if (newArray.destination == interestingRegister) {
|
|
return newArray.newSiteRef.getDeclaredType().getArrayElementType();
|
|
}
|
|
} else if (curInst.getOpcode() == Opcode.MOVE_OBJECT || curInst.getOpcode() == Opcode.MOVE_OBJECT_16 || curInst.getOpcode() == Opcode.MOVE_OBJECT_FROM16) {
|
|
TwoRegisterInstruction tri = (TwoRegisterInstruction) curInst;
|
|
int regA = tri.getRegisterA();
|
|
int regB = tri.getRegisterB();
|
|
if (regA == interestingRegister) {
|
|
interestingRegister = regB;
|
|
}
|
|
}
|
|
// all other instructions are ignored
|
|
curCounter--;
|
|
}
|
|
|
|
throw new UnsupportedOperationException("found a fill-array-data instruction without a corresponding new-array instruction. This should not happen!");
|
|
}
|
|
|
|
protected void handleINVOKE_VIRTUAL(int instLoc, String cname, String mname, String pname, int[] args, Opcode opcode ) {
|
|
instructions.add(new Invoke.InvokeVirtual(instLoc, cname, mname, pname, args, opcode, this));
|
|
}
|
|
|
|
public Instruction[] getDexInstructions() {
|
|
return instructions().toArray(new Instruction[instructions().size()]);
|
|
}
|
|
|
|
|
|
|
|
protected InstructionArray instructions(){
|
|
if (instructions == null)
|
|
parseBytecode();
|
|
return instructions;
|
|
}
|
|
|
|
public int getAddressFromIndex(int index) {
|
|
return instructions().getPcFromIndex(index);
|
|
}
|
|
|
|
@Override
|
|
public int getInstructionIndex(int bytecodeindex) {
|
|
return instructions().getIndexFromPc(bytecodeindex);
|
|
}
|
|
|
|
public Instruction getInstructionFromIndex(int instructionIndex) {
|
|
return instructions().getFromId(instructionIndex);
|
|
}
|
|
|
|
private static final IndirectionData NO_INDIRECTIONS = new IndirectionData() {
|
|
|
|
private final int[] NOTHING = new int[0];
|
|
|
|
@Override
|
|
public int[] indirectlyReadLocals(int instructionIndex) {
|
|
return NOTHING;
|
|
}
|
|
|
|
@Override
|
|
public int[] indirectlyWrittenLocals(int instructionIndex) {
|
|
return NOTHING;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
@Override
|
|
public IndirectionData getIndirectionData() {
|
|
return NO_INDIRECTIONS;
|
|
}
|
|
|
|
//-------------------------------------------
|
|
// MethodAnnotationIteratorDelegate Methods
|
|
//-------------------------------------------
|
|
|
|
|
|
// /**
|
|
// * Delegate called by the class in order to parse the method annotations.
|
|
// */
|
|
// public void processMethodAnnotations(MethodIdItem mIdItem,
|
|
// AnnotationSetItem anoSet) {
|
|
// //System.out.println("DexIMethod: processMethodAnnotations()");
|
|
// if ( mIdItem.equals(eMethod.method) ){
|
|
// AnnotationItem[] items = anoSet.getAnnotations();
|
|
// for (AnnotationItem item : items) {
|
|
//
|
|
// }
|
|
//
|
|
// }
|
|
// }
|
|
|
|
/**
|
|
*
|
|
* @throws UnsupportedOperationException
|
|
*
|
|
* TODO: Review this implementation - it may be horribly wrong!
|
|
*/
|
|
@Override
|
|
public Collection<CallSiteReference> getCallSites() {
|
|
Collection<CallSiteReference> empty = Collections.emptySet();
|
|
if (isNative()) {
|
|
return empty;
|
|
}
|
|
|
|
// assert(false) : "Please review getCallSites-Implementation before use!"; // TODO
|
|
|
|
ArrayList<CallSiteReference> csites = new ArrayList<>();
|
|
// XXX The call Sites in this method or to this method?!!!
|
|
for (Instruction inst: instructions()) {
|
|
if (inst instanceof Invoke) {
|
|
// Locate the Target
|
|
MethodReference target = MethodReference.findOrCreate(
|
|
getDeclaringClass().getClassLoader().getReference(), // XXX: Is this the correct class loader?
|
|
((Invoke)inst).clazzName,
|
|
((Invoke)inst).methodName,
|
|
((Invoke)inst).descriptor );
|
|
|
|
csites.add(
|
|
CallSiteReference.make(
|
|
inst.pc, // programCounter
|
|
target, // declaredTarget
|
|
((Invoke)inst).getInvocationCode() // invocationCode
|
|
));
|
|
}
|
|
}
|
|
return Collections.unmodifiableCollection(csites);
|
|
}
|
|
|
|
@Override
|
|
public SourcePosition getSourcePosition(int instructionIndex) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public SourcePosition getParameterSourcePosition(int paramNum) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Collection<Annotation> getAnnotations() {
|
|
return myClass.getAnnotations(eMethod, null);
|
|
}
|
|
|
|
@Override
|
|
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) {
|
|
return myClass.getAnnotations(eMethod, DexIClass.getTypes(runtimeInvisible));
|
|
}
|
|
|
|
@Override
|
|
public Collection<Annotation>[] getParameterAnnotations() {
|
|
Map<Integer, List<Annotation>> raw = myClass.getParameterAnnotations(eMethod);
|
|
@SuppressWarnings("unchecked")
|
|
Collection<Annotation>[] result = new Collection[ getReference().getNumberOfParameters() ];
|
|
for(Map.Entry<Integer, List<Annotation>> x : raw.entrySet()) {
|
|
result[x.getKey()] = x.getValue();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
}
|