use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class AnalyzedInstruction method getSetRegisters.
public List<Integer> getSetRegisters() {
List<Integer> setRegisters = Lists.newArrayList();
if (instruction.getOpcode().setsRegister()) {
setRegisters.add(getDestinationRegister());
}
if (instruction.getOpcode().setsWideRegister()) {
setRegisters.add(getDestinationRegister() + 1);
}
if (isInvokeInit()) {
//When constructing a new object, the register type will be an uninitialized reference after the new-instance
//instruction, but becomes an initialized reference once the <init> method is called. So even though invoke
//instructions don't normally change any registers, calling an <init> method will change the type of its
//object register. If the uninitialized reference has been copied to other registers, they will be initialized
//as well, so we need to check for that too
int destinationRegister;
if (instruction instanceof FiveRegisterInstruction) {
destinationRegister = ((FiveRegisterInstruction) instruction).getRegisterC();
assert ((FiveRegisterInstruction) instruction).getRegisterCount() > 0;
} else {
assert instruction instanceof RegisterRangeInstruction;
RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction) instruction;
assert rangeInstruction.getRegisterCount() > 0;
destinationRegister = rangeInstruction.getStartRegister();
}
RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(destinationRegister);
if (preInstructionDestRegisterType.category == RegisterType.UNINIT_REF || preInstructionDestRegisterType.category == RegisterType.UNINIT_THIS) {
setRegisters.add(destinationRegister);
RegisterType objectRegisterType = preRegisterMap[destinationRegister];
for (int i = 0; i < preRegisterMap.length; i++) {
if (i == destinationRegister) {
continue;
}
RegisterType preInstructionRegisterType = preRegisterMap[i];
if (preInstructionRegisterType.equals(objectRegisterType)) {
setRegisters.add(i);
} else if (preInstructionRegisterType.category == RegisterType.UNINIT_REF || preInstructionRegisterType.category == RegisterType.UNINIT_THIS) {
RegisterType postInstructionRegisterType = postRegisterMap[i];
if (postInstructionRegisterType.category == RegisterType.UNKNOWN) {
setRegisters.add(i);
}
}
}
} else if (preInstructionDestRegisterType.category == RegisterType.UNKNOWN) {
for (int i = 0; i < preRegisterMap.length; i++) {
RegisterType registerType = preRegisterMap[i];
if (registerType.category == RegisterType.UNINIT_REF || registerType.category == RegisterType.UNINIT_THIS) {
setRegisters.add(i);
}
}
}
}
// branch of the following if-eqz/if-nez
if (instructionIndex > 0 && methodAnalyzer.getClassPath().isArt() && getPredecessorCount() == 1 && (instruction.getOpcode() == Opcode.IF_EQZ || instruction.getOpcode() == Opcode.IF_NEZ)) {
AnalyzedInstruction prevInstruction = predecessors.first();
if (prevInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF && MethodAnalyzer.canPropagateTypeAfterInstanceOf(prevInstruction, this, methodAnalyzer.getClassPath())) {
Instruction22c instanceOfInstruction = (Instruction22c) prevInstruction.instruction;
setRegisters.add(instanceOfInstruction.getRegisterB());
// TODO: do we need to do some sort of additional check that these multiple move-object predecessors actually refer to the same value?
if (instructionIndex > 1) {
int originalSourceRegister = -1;
RegisterType newType = null;
for (AnalyzedInstruction prevPrevAnalyzedInstruction : prevInstruction.predecessors) {
Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode();
if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || opcode == Opcode.MOVE_OBJECT_FROM16) {
TwoRegisterInstruction moveInstruction = ((TwoRegisterInstruction) prevPrevAnalyzedInstruction.instruction);
RegisterType originalType = prevPrevAnalyzedInstruction.getPostInstructionRegisterType(moveInstruction.getRegisterB());
if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) {
originalSourceRegister = -1;
break;
}
if (originalType.type == null) {
originalSourceRegister = -1;
break;
}
if (newType == null) {
newType = RegisterType.getRegisterType(methodAnalyzer.getClassPath(), (TypeReference) instanceOfInstruction.getReference());
}
if (MethodAnalyzer.isNotWideningConversion(originalType, newType)) {
if (originalSourceRegister != -1) {
if (originalSourceRegister != moveInstruction.getRegisterB()) {
originalSourceRegister = -1;
break;
}
} else {
originalSourceRegister = moveInstruction.getRegisterB();
}
}
} else {
originalSourceRegister = -1;
break;
}
}
if (originalSourceRegister != -1) {
setRegisters.add(originalSourceRegister);
}
}
}
}
return setRegisters;
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class AnalyzedMethodUtil method canAccess.
public static boolean canAccess(@Nonnull TypeProto type, @Nonnull Method virtualMethod, boolean checkPackagePrivate, boolean checkProtected, boolean checkClass) {
if (checkPackagePrivate && MethodUtil.isPackagePrivate(virtualMethod)) {
String otherPackage = TypeUtils.getPackage(virtualMethod.getDefiningClass());
String thisPackage = TypeUtils.getPackage(type.getType());
if (!otherPackage.equals(thisPackage)) {
return false;
}
}
if (checkProtected && (virtualMethod.getAccessFlags() & AccessFlags.PROTECTED.getValue()) != 0) {
if (!TypeProtoUtils.extendsFrom(type, virtualMethod.getDefiningClass())) {
return false;
}
}
if (checkClass) {
ClassPath classPath = type.getClassPath();
ClassDef methodClassDef = classPath.getClassDef(virtualMethod.getDefiningClass());
if (!TypeUtils.canAccessClass(type.getType(), methodClassDef)) {
return false;
}
}
return true;
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class CustomInlineMethodResolver method resolveExecuteInline.
@Override
@Nonnull
public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) {
InlineIndexInstruction instruction = (InlineIndexInstruction) analyzedInstruction.instruction;
int methodIndex = instruction.getInlineIndex();
if (methodIndex < 0 || methodIndex >= inlineMethods.length) {
throw new RuntimeException("Invalid method index: " + methodIndex);
}
return inlineMethods[methodIndex];
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class ListVtablesCommand method listClassVtable.
private void listClassVtable(ClassProto classProto) throws IOException {
List<Method> methods = classProto.getVtable();
String className = "Class " + classProto.getType() + " extends " + classProto.getSuperclass() + " : " + methods.size() + " methods\n";
System.out.write(className.getBytes());
for (int i = 0; i < methods.size(); i++) {
Method method = methods.get(i);
String methodString = i + ":" + method.getDefiningClass() + "->" + method.getName() + "(";
for (CharSequence parameter : method.getParameterTypes()) {
methodString += parameter;
}
methodString += ")" + method.getReturnType() + "\n";
System.out.write(methodString.getBytes());
}
System.out.write("\n".getBytes());
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class ClassDefinition method writeDirectMethods.
private Set<String> writeDirectMethods(IndentingWriter writer) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> directMethods;
if (classDef instanceof DexBackedClassDef) {
directMethods = ((DexBackedClassDef) classDef).getDirectMethods(false);
} else {
directMethods = classDef.getDirectMethods();
}
for (Method method : directMethods) {
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# direct methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
IndentingWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = new CommentingIndentingWriter(writer);
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);
}
}
return writtenMethods;
}
Aggregations