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;
}
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());
}
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;
}
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;
}
}
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;
}
Aggregations