Search in sources :

Example 1 with SmaliInstruction

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

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

the class SmaliInstructionTest method testMultipleInstructions.

public void testMultipleInstructions() {
    String text = ".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" + ".method blah(IJLjava/lang/String;)I\n" + "    .locals 1\n" + "    const v0, 1234\n" + "    r<ref>eturn v0\n" + ".end method";
    SmaliFile file = (SmaliFile) myFixture.addFileToProject("my/pkg/blah.smali", text.replace("<ref>", ""));
    PsiElement leafElement = file.findElementAt(text.indexOf("<ref>"));
    Assert.assertNotNull(leafElement);
    SmaliInstruction instructionElement = (SmaliInstruction) leafElement.getParent();
    Assert.assertNotNull(instructionElement);
    Assert.assertEquals(Opcode.RETURN, instructionElement.getOpcode());
    Assert.assertEquals(6, instructionElement.getOffset());
}
Also used : SmaliFile(org.jf.smalidea.psi.impl.SmaliFile) SmaliInstruction(org.jf.smalidea.psi.impl.SmaliInstruction) PsiElement(com.intellij.psi.PsiElement)

Example 3 with SmaliInstruction

use of org.jf.smalidea.psi.impl.SmaliInstruction 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 4 with SmaliInstruction

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

the class SmaliCodeFragmentFactory method evaluateRegister.

@Nullable
public static Value evaluateRegister(EvaluationContext context, final SmaliMethod smaliMethod, final int registerNum, final String type) throws EvaluateException {
    if (registerNum >= smaliMethod.getRegisterCount()) {
        return null;
    }
    final StackFrameProxy frameProxy = context.getSuspendContext().getFrameProxy();
    if (frameProxy == null) {
        return null;
    }
    VirtualMachine vm = frameProxy.getStackFrame().virtualMachine();
    Location currentLocation = frameProxy.location();
    if (currentLocation == null) {
        return null;
    }
    Method method = currentLocation.method();
    try {
        final Constructor<LocalVariableImpl> localVariableConstructor = LocalVariableImpl.class.getDeclaredConstructor(VirtualMachine.class, Method.class, Integer.TYPE, Location.class, Location.class, String.class, String.class, String.class);
        localVariableConstructor.setAccessible(true);
        Constructor<LocationImpl> locationConstructor = LocationImpl.class.getDeclaredConstructor(VirtualMachine.class, Method.class, Long.TYPE);
        locationConstructor.setAccessible(true);
        int methodSize = 0;
        for (SmaliInstruction instruction : smaliMethod.getInstructions()) {
            methodSize += instruction.getInstructionSize();
        }
        Location endLocation = null;
        for (int endCodeIndex = (methodSize / 2) - 1; endCodeIndex >= 0; endCodeIndex--) {
            endLocation = method.locationOfCodeIndex(endCodeIndex);
            if (endLocation != null) {
                break;
            }
        }
        if (endLocation == null) {
            return null;
        }
        LocalVariable localVariable = localVariableConstructor.newInstance(vm, method, mapRegister(frameProxy.getStackFrame().virtualMachine(), smaliMethod, registerNum), method.location(), endLocation, String.format("v%d", registerNum), type, null);
        return frameProxy.getStackFrame().getValue(localVariable);
    } catch (NoSuchMethodException e) {
        return null;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    } catch (InvocationTargetException e) {
        return null;
    }
}
Also used : LocalVariableImpl(com.sun.tools.jdi.LocalVariableImpl) StackFrameProxy(com.intellij.debugger.engine.jdi.StackFrameProxy) PsiLocalVariable(com.intellij.psi.PsiLocalVariable) SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod) SmaliInstruction(org.jf.smalidea.psi.impl.SmaliInstruction) InvocationTargetException(java.lang.reflect.InvocationTargetException) LocationImpl(com.sun.tools.jdi.LocationImpl) Nullable(javax.annotation.Nullable)

Example 5 with SmaliInstruction

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

the class InstructionUtils method findFirstInstructionWithTarget.

@Nullable
public static SmaliInstruction findFirstInstructionWithTarget(@NotNull SmaliMethod method, @NotNull Opcode opcode, int targetOffset) {
    for (SmaliInstruction instruction : method.getInstructions()) {
        if (instruction.getOpcode() == opcode) {
            SmaliLabelReference labelReference = instruction.getTarget();
            if (labelReference == null) {
                continue;
            }
            SmaliLabel label = labelReference.resolve();
            if (label == null) {
                continue;
            }
            if (label.getOffset() == targetOffset) {
                return instruction;
            }
        }
    }
    return null;
}
Also used : SmaliLabelReference(org.jf.smalidea.psi.impl.SmaliLabelReference) SmaliInstruction(org.jf.smalidea.psi.impl.SmaliInstruction) SmaliLabel(org.jf.smalidea.psi.impl.SmaliLabel) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

SmaliInstruction (org.jf.smalidea.psi.impl.SmaliInstruction)7 PsiElement (com.intellij.psi.PsiElement)3 SmaliMethod (org.jf.smalidea.psi.impl.SmaliMethod)3 PsiLocalVariable (com.intellij.psi.PsiLocalVariable)2 Nullable (org.jetbrains.annotations.Nullable)2 SmaliFile (org.jf.smalidea.psi.impl.SmaliFile)2 SmaliLabel (org.jf.smalidea.psi.impl.SmaliLabel)2 SmaliLabelReference (org.jf.smalidea.psi.impl.SmaliLabelReference)2 StackFrameProxy (com.intellij.debugger.engine.jdi.StackFrameProxy)1 JavaCodeFragment (com.intellij.psi.JavaCodeFragment)1 JavaRecursiveElementVisitor (com.intellij.psi.JavaRecursiveElementVisitor)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 AnalyzedInstruction (org.jf.dexlib2.analysis.AnalyzedInstruction)1 RegisterType (org.jf.dexlib2.analysis.RegisterType)1 Instruction (org.jf.dexlib2.iface.instruction.Instruction)1 LazyValue (org.jf.smalidea.debugging.value.LazyValue)1 SmalideaInstruction (org.jf.smalidea.dexlib.instruction.SmalideaInstruction)1