Search in sources :

Example 1 with SmaliMethod

use of org.jf.smalidea.psi.impl.SmaliMethod in project smali by JesusFreke.

the class SmalideaMethod method getImplementation.

@Nullable
@Override
public MethodImplementation getImplementation() {
    if (psiMethod instanceof SmaliMethod) {
        final SmaliMethod smaliMethod = (SmaliMethod) this.psiMethod;
        List<SmaliInstruction> instructions = smaliMethod.getInstructions();
        if (instructions.size() == 0) {
            return null;
        }
        // TODO: cache this?
        return new MethodImplementation() {

            @Override
            public int getRegisterCount() {
                return smaliMethod.getRegisterCount();
            }

            @Nonnull
            @Override
            public Iterable<? extends Instruction> getInstructions() {
                return Lists.transform(smaliMethod.getInstructions(), new Function<SmaliInstruction, Instruction>() {

                    @Override
                    public Instruction apply(SmaliInstruction smaliInstruction) {
                        return SmalideaInstruction.of(smaliInstruction);
                    }
                });
            }

            @Nonnull
            @Override
            public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks() {
                return Lists.transform(smaliMethod.getCatchStatements(), new Function<SmaliCatchStatement, TryBlock<? extends ExceptionHandler>>() {

                    @Override
                    public TryBlock<? extends ExceptionHandler> apply(SmaliCatchStatement smaliCatchStatement) {
                        assert smaliCatchStatement != null;
                        return new SmalideaTryBlock(smaliCatchStatement);
                    }
                });
            }

            @Nonnull
            @Override
            public Iterable<? extends DebugItem> getDebugItems() {
                // TODO: implement this
                return ImmutableList.of();
            }
        };
    }
    return null;
}
Also used : SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod) SmaliCatchStatement(org.jf.smalidea.psi.impl.SmaliCatchStatement) SmaliInstruction(org.jf.smalidea.psi.impl.SmaliInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) SmaliInstruction(org.jf.smalidea.psi.impl.SmaliInstruction) SmalideaInstruction(org.jf.smalidea.dexlib.instruction.SmalideaInstruction) Nullable(org.jetbrains.annotations.Nullable)

Example 2 with SmaliMethod

use of org.jf.smalidea.psi.impl.SmaliMethod in project smali by JesusFreke.

the class SmalideaMethod method getAccessFlags.

@Override
public int getAccessFlags() {
    if (psiMethod instanceof SmaliMethod) {
        return ((SmaliMethod) psiMethod).getModifierList().getAccessFlags();
    } else {
        int flags = 0;
        PsiModifierList modifierList = psiMethod.getModifierList();
        if (modifierList.hasModifierProperty("public")) {
            flags |= AccessFlags.PUBLIC.getValue();
        } else if (modifierList.hasModifierProperty("protected")) {
            flags |= AccessFlags.PROTECTED.getValue();
        } else if (modifierList.hasModifierProperty("private")) {
            flags |= AccessFlags.PRIVATE.getValue();
        }
        if (modifierList.hasModifierProperty("static")) {
            flags |= AccessFlags.STATIC.getValue();
        }
        if (modifierList.hasModifierProperty("final")) {
            flags |= AccessFlags.FINAL.getValue();
        }
        boolean isNative = false;
        if (modifierList.hasModifierProperty("native")) {
            flags |= AccessFlags.NATIVE.getValue();
            isNative = true;
        }
        if (modifierList.hasModifierProperty("synchronized")) {
            if (isNative) {
                flags |= AccessFlags.SYNCHRONIZED.getValue();
            } else {
                flags |= AccessFlags.DECLARED_SYNCHRONIZED.getValue();
            }
        }
        if (psiMethod.isVarArgs()) {
            flags |= AccessFlags.VARARGS.getValue();
        }
        if (modifierList.hasModifierProperty("abstract")) {
            flags |= AccessFlags.ABSTRACT.getValue();
        }
        if (modifierList.hasModifierProperty("strictfp")) {
            flags |= AccessFlags.STRICTFP.getValue();
        }
        if (psiMethod.isConstructor()) {
            flags |= AccessFlags.CONSTRUCTOR.getValue();
        }
        return flags;
    }
}
Also used : SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod) PsiModifierList(com.intellij.psi.PsiModifierList)

Example 3 with SmaliMethod

use of org.jf.smalidea.psi.impl.SmaliMethod in project smali by JesusFreke.

the class SmalideaMethodTest method testSparseSwitch.

public void testSparseSwitch() {
    String text = ".class public LFormat31t;\n" + ".super Ljava/lang/Object;\n" + ".source \"Format31t.smali\"" + "\n" + ".method public test_sparse-switch()V\n" + "    .registers 1\n" + "    .annotation runtime Lorg/junit/Test;\n" + "    .end annotation\n" + "\n" + "    const v0, 13\n" + "\n" + ":switch\n" + "    sparse-switch v0, :SparseSwitch\n" + "\n" + ":Label10\n" + "    invoke-static {}, Lorg/junit/Assert;->fail()V\n" + "    return-void\n" + "\n" + ":Label20\n" + "    invoke-static {}, Lorg/junit/Assert;->fail()V\n" + "    return-void\n" + "\n" + ":Label15\n" + "    invoke-static {}, Lorg/junit/Assert;->fail()V\n" + "    return-void\n" + "\n" + ":Label13\n" + "    return-void\n" + "\n" + ":Label99\n" + "    invoke-static {}, Lorg/junit/Assert;->fail()V\n" + "    return-void\n" + "\n" + ":SparseSwitch\n" + "    .sparse-switch\n" + "        10 -> :Label10\n" + "        13 -> :Label13\n" + "        15 -> :Label15\n" + "        20 -> :Label20\n" + "        99 -> :Label99\n" + "    .end sparse-switch\n" + ".end method";
    SmaliFile file = (SmaliFile) myFixture.addFileToProject("my/pkg/blah.smali", text);
    SmaliClass smaliClass = file.getPsiClass();
    SmaliMethod smaliMethod = smaliClass.getMethods()[0];
    SmalideaMethod method = new SmalideaMethod(smaliMethod);
    MethodImplementation impl = method.getImplementation();
    Assert.assertNotNull(impl);
    List<Instruction> instructions = Lists.newArrayList(impl.getInstructions());
    SparseSwitchPayload sparseSwitchPayload = (SparseSwitchPayload) instructions.get(11);
    List<? extends SwitchElement> switchElements = sparseSwitchPayload.getSwitchElements();
    Assert.assertEquals(5, switchElements.size());
    checkSwitchElement(switchElements.get(0), 10, 6);
    checkSwitchElement(switchElements.get(1), 13, 30);
    checkSwitchElement(switchElements.get(2), 15, 22);
    checkSwitchElement(switchElements.get(3), 20, 14);
    checkSwitchElement(switchElements.get(4), 99, 32);
}
Also used : SmaliFile(org.jf.smalidea.psi.impl.SmaliFile) MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) SmaliClass(org.jf.smalidea.psi.impl.SmaliClass) SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod) Instruction(org.jf.dexlib2.iface.instruction.Instruction)

Example 4 with SmaliMethod

use of org.jf.smalidea.psi.impl.SmaliMethod in project smali by JesusFreke.

the class SmaliAnnotationTest method testMethodAnnotation.

public void testMethodAnnotation() {
    myFixture.addFileToProject("my/TestAnnotation.smali", ".class public interface abstract annotation Lmy/TestAnnotation;\n" + ".super Ljava/lang/Object;\n" + ".implements Ljava/lang/annotation/Annotation;\n" + "\n" + ".method public abstract testBooleanValue()Z\n" + ".end method\n" + "\n" + ".method public abstract testStringArrayValue()[Ljava/lang/String;\n" + ".end method\n" + "\n" + ".method public abstract testStringValue()Ljava/lang/String;\n" + ".end method");
    myFixture.addFileToProject("my/TestAnnotation2.smali", ".class public interface abstract annotation Lmy/TestAnnotation2;\n" + ".super Ljava/lang/Object;\n" + ".implements Ljava/lang/annotation/Annotation;\n");
    SmaliFile file = (SmaliFile) myFixture.addFileToProject("my/pkg/blah.smali", ".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" + "\n" + ".method public myMethod()V\n" + "    .annotation runtime Lmy/TestAnnotation;\n" + "        testBooleanValue = true\n" + "        testStringValue = \"blah\"\n" + "        testStringArrayValue = {\n" + "            \"blah1\",\n" + "            \"blah2\"\n" + "        }\n" + "    .end annotation\n" + "    .annotation runtime Lmy/TestAnnotation2;\n" + "    .end annotation\n" + ".end method");
    SmaliClass smaliClass = file.getPsiClass();
    Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
    SmaliMethod method = smaliClass.getMethods()[0];
    doTest(method);
}
Also used : SmaliFile(org.jf.smalidea.psi.impl.SmaliFile) SmaliClass(org.jf.smalidea.psi.impl.SmaliClass) SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod)

Example 5 with SmaliMethod

use of org.jf.smalidea.psi.impl.SmaliMethod 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)

Aggregations

SmaliMethod (org.jf.smalidea.psi.impl.SmaliMethod)11 SmaliClass (org.jf.smalidea.psi.impl.SmaliClass)7 SmaliFile (org.jf.smalidea.psi.impl.SmaliFile)7 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)5 Instruction (org.jf.dexlib2.iface.instruction.Instruction)4 SmaliInstruction (org.jf.smalidea.psi.impl.SmaliInstruction)3 PsiLocalVariable (com.intellij.psi.PsiLocalVariable)2 StackFrameProxy (com.intellij.debugger.engine.jdi.StackFrameProxy)1 JavaCodeFragment (com.intellij.psi.JavaCodeFragment)1 JavaRecursiveElementVisitor (com.intellij.psi.JavaRecursiveElementVisitor)1 PsiElement (com.intellij.psi.PsiElement)1 PsiModifierList (com.intellij.psi.PsiModifierList)1 LocalVariableImpl (com.sun.tools.jdi.LocalVariableImpl)1 LocationImpl (com.sun.tools.jdi.LocationImpl)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Nullable (javax.annotation.Nullable)1 Nullable (org.jetbrains.annotations.Nullable)1 AnalyzedInstruction (org.jf.dexlib2.analysis.AnalyzedInstruction)1 RegisterType (org.jf.dexlib2.analysis.RegisterType)1 StringReference (org.jf.dexlib2.iface.reference.StringReference)1