Search in sources :

Example 26 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.

the class SmaliCodeFragmentFactory method wrapContext.

private PsiElement wrapContext(final Project project, final PsiElement originalContext) {
    if (project.isDefault())
        return originalContext;
    final List<LazyValue> lazyValues = Lists.newArrayList();
    SmaliInstruction currentInstruction = (SmaliInstruction) PsiUtil.searchBackward(originalContext, PsiMatchers.hasClass(SmaliInstruction.class), PsiMatchers.hasClass(SmaliMethod.class));
    if (currentInstruction == null) {
        currentInstruction = (SmaliInstruction) PsiUtil.searchForward(originalContext, PsiMatchers.hasClass(SmaliInstruction.class), PsiMatchers.hasClass(SmaliMethod.class));
        if (currentInstruction == null) {
            return originalContext;
        }
    }
    final SmaliMethod containingMethod = currentInstruction.getParentMethod();
    AnalyzedInstruction analyzedInstruction = currentInstruction.getAnalyzedInstruction();
    if (analyzedInstruction == null) {
        return originalContext;
    }
    final int firstParameterRegister = containingMethod.getRegisterCount() - containingMethod.getParameterRegisterCount();
    final Map<String, String> registerMap = Maps.newHashMap();
    StringBuilder variablesText = new StringBuilder();
    for (int i = 0; i < containingMethod.getRegisterCount(); i++) {
        int parameterRegisterNumber = i - firstParameterRegister;
        RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(i);
        switch(registerType.category) {
            case RegisterType.UNKNOWN:
            case RegisterType.UNINIT:
            case RegisterType.CONFLICTED:
            case RegisterType.LONG_HI:
            case RegisterType.DOUBLE_HI:
                continue;
            case RegisterType.NULL:
            case RegisterType.ONE:
            case RegisterType.INTEGER:
                variablesText.append("int v").append(i).append(";\n");
                registerMap.put("v" + i, "I");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("int p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "I");
                }
                break;
            case RegisterType.BOOLEAN:
                variablesText.append("boolean v").append(i).append(";\n");
                registerMap.put("v" + i, "Z");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("boolean p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "Z");
                }
                break;
            case RegisterType.BYTE:
            case RegisterType.POS_BYTE:
                variablesText.append("byte v").append(i).append(";\n");
                registerMap.put("v" + i, "B");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("byte p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "B");
                }
                break;
            case RegisterType.SHORT:
            case RegisterType.POS_SHORT:
                variablesText.append("short v").append(i).append(";\n");
                registerMap.put("v" + i, "S");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("short p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "S");
                }
                break;
            case RegisterType.CHAR:
                variablesText.append("char v").append(i).append(";\n");
                registerMap.put("v" + i, "C");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("char p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "C");
                }
                break;
            case RegisterType.FLOAT:
                variablesText.append("float v").append(i).append(";\n");
                registerMap.put("v" + i, "F");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("float p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "F");
                }
                break;
            case RegisterType.LONG_LO:
                variablesText.append("long v").append(i).append(";\n");
                registerMap.put("v" + i, "J");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("long p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "J");
                }
                break;
            case RegisterType.DOUBLE_LO:
                variablesText.append("double v").append(i).append(";\n");
                registerMap.put("v" + i, "D");
                if (parameterRegisterNumber >= 0) {
                    variablesText.append("double p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "D");
                }
                break;
            case RegisterType.UNINIT_REF:
            case RegisterType.UNINIT_THIS:
            case RegisterType.REFERENCE:
                String smaliType = registerType.type.getType();
                String javaType = NameUtils.smaliToJavaType(smaliType);
                variablesText.append(javaType).append(" v").append(i).append(";\n");
                registerMap.put("v" + i, smaliType);
                if (parameterRegisterNumber >= 0) {
                    variablesText.append(javaType).append(" p").append(parameterRegisterNumber).append(";\n");
                    registerMap.put("p" + parameterRegisterNumber, "Ljava/lang/Object;");
                }
                break;
        }
    }
    final TextWithImportsImpl textWithImports = new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, variablesText.toString(), "", getFileType());
    final JavaCodeFragment codeFragment = super.createCodeFragment(textWithImports, originalContext, project);
    codeFragment.accept(new JavaRecursiveElementVisitor() {

        @Override
        public void visitLocalVariable(final PsiLocalVariable variable) {
            final String name = variable.getName();
            if (name != null && registerMap.containsKey(name)) {
                int registerNumber = Integer.parseInt(name.substring(1));
                if (name.charAt(0) == 'p') {
                    registerNumber += ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {

                        @Override
                        public Integer compute() {
                            return containingMethod.getRegisterCount() - containingMethod.getParameterRegisterCount();
                        }
                    });
                }
                LazyValue lazyValue = LazyValue.create(containingMethod, project, registerNumber, registerMap.get(name));
                variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, lazyValue);
                lazyValues.add(lazyValue);
            }
        }
    });
    int offset = variablesText.length() - 1;
    final PsiElement newContext = codeFragment.findElementAt(offset);
    if (newContext != null) {
        newContext.putUserData(SMALI_LAZY_VALUES_KEY, lazyValues);
        return newContext;
    }
    return originalContext;
}
Also used : LazyValue(org.jf.smalidea.debugging.value.LazyValue) SmaliInstruction(org.jf.smalidea.psi.impl.SmaliInstruction) PsiLocalVariable(com.intellij.psi.PsiLocalVariable) AnalyzedInstruction(org.jf.dexlib2.analysis.AnalyzedInstruction) SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod) RegisterType(org.jf.dexlib2.analysis.RegisterType) JavaCodeFragment(com.intellij.psi.JavaCodeFragment) JavaRecursiveElementVisitor(com.intellij.psi.JavaRecursiveElementVisitor) PsiElement(com.intellij.psi.PsiElement)

Example 27 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.

the class MethodAnalyzerTest method testInstanceOfNarrowingAfterMove_art.

@Test
public void testInstanceOfNarrowingAfterMove_art() throws IOException {
    MethodImplementationBuilder builder = new MethodImplementationBuilder(3);
    builder.addInstruction(new BuilderInstruction12x(Opcode.MOVE_OBJECT, 1, 2));
    builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;")));
    builder.addInstruction(new BuilderInstruction21t(Opcode.IF_EQZ, 0, builder.getLabel("not_instance_of")));
    builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
    builder.addLabel("not_instance_of");
    builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
    MethodImplementation methodImplementation = builder.getMethodImplementation();
    Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation);
    ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method));
    DexFile dexFile = new ImmutableDexFile(forArtVersion(56), Collections.singletonList(classDef));
    ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), true, 56);
    MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false);
    List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions();
    Assert.assertEquals("Lmain;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType());
    Assert.assertEquals("Lmain;", analyzedInstructions.get(3).getPreInstructionRegisterType(2).type.getType());
    Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(4).getPreInstructionRegisterType(1).type.getType());
    Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(4).getPreInstructionRegisterType(2).type.getType());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction12x(org.jf.dexlib2.builder.instruction.BuilderInstruction12x) ImmutableMethod(org.jf.dexlib2.immutable.ImmutableMethod) ImmutableClassDef(org.jf.dexlib2.immutable.ImmutableClassDef) ImmutableMethodParameter(org.jf.dexlib2.immutable.ImmutableMethodParameter) BuilderInstruction21t(org.jf.dexlib2.builder.instruction.BuilderInstruction21t) ImmutableMethod(org.jf.dexlib2.immutable.ImmutableMethod) Method(org.jf.dexlib2.iface.Method) DexFile(org.jf.dexlib2.iface.DexFile) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) ImmutableClassDef(org.jf.dexlib2.immutable.ImmutableClassDef) ClassDef(org.jf.dexlib2.iface.ClassDef) BuilderInstruction22c(org.jf.dexlib2.builder.instruction.BuilderInstruction22c) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) MethodImplementationBuilder(org.jf.dexlib2.builder.MethodImplementationBuilder) Test(org.junit.Test)

Example 28 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.

the class MethodAnalyzerTest method testInstanceOfNarrowingAfterMove_dalvik.

@Test
public void testInstanceOfNarrowingAfterMove_dalvik() throws IOException {
    MethodImplementationBuilder builder = new MethodImplementationBuilder(3);
    builder.addInstruction(new BuilderInstruction12x(Opcode.MOVE_OBJECT, 1, 2));
    builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;")));
    builder.addInstruction(new BuilderInstruction21t(Opcode.IF_EQZ, 0, builder.getLabel("not_instance_of")));
    builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
    builder.addLabel("not_instance_of");
    builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
    MethodImplementation methodImplementation = builder.getMethodImplementation();
    Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation);
    ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method));
    DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), Collections.singletonList(classDef));
    ClassPath classPath = new ClassPath(new DexClassProvider(dexFile));
    MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false);
    List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions();
    Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType());
    Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(2).type.getType());
    Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(4).getPreInstructionRegisterType(1).type.getType());
    Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(4).getPreInstructionRegisterType(2).type.getType());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction12x(org.jf.dexlib2.builder.instruction.BuilderInstruction12x) ImmutableMethod(org.jf.dexlib2.immutable.ImmutableMethod) ImmutableClassDef(org.jf.dexlib2.immutable.ImmutableClassDef) ImmutableMethodParameter(org.jf.dexlib2.immutable.ImmutableMethodParameter) BuilderInstruction21t(org.jf.dexlib2.builder.instruction.BuilderInstruction21t) ImmutableMethod(org.jf.dexlib2.immutable.ImmutableMethod) Method(org.jf.dexlib2.iface.Method) DexFile(org.jf.dexlib2.iface.DexFile) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) ImmutableClassDef(org.jf.dexlib2.immutable.ImmutableClassDef) ClassDef(org.jf.dexlib2.iface.ClassDef) BuilderInstruction22c(org.jf.dexlib2.builder.instruction.BuilderInstruction22c) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) MethodImplementationBuilder(org.jf.dexlib2.builder.MethodImplementationBuilder) Test(org.junit.Test)

Aggregations

Opcode (org.jf.dexlib2.Opcode)8 TypeReference (org.jf.dexlib2.iface.reference.TypeReference)7 AnalyzedInstruction (org.jf.dexlib2.analysis.AnalyzedInstruction)6 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)6 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)6 BuilderInstruction21t (org.jf.dexlib2.builder.instruction.BuilderInstruction21t)6 BuilderInstruction22c (org.jf.dexlib2.builder.instruction.BuilderInstruction22c)6 ClassDef (org.jf.dexlib2.iface.ClassDef)6 DexFile (org.jf.dexlib2.iface.DexFile)6 Method (org.jf.dexlib2.iface.Method)6 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)6 ImmutableClassDef (org.jf.dexlib2.immutable.ImmutableClassDef)6 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)6 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)6 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)6 ImmutableTypeReference (org.jf.dexlib2.immutable.reference.ImmutableTypeReference)6 Test (org.junit.Test)6 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)5 ImmutableFieldReference (org.jf.dexlib2.immutable.reference.ImmutableFieldReference)5 BaseMethodReference (org.jf.dexlib2.base.reference.BaseMethodReference)4