Fix some warnings in the debugger code

This commit is contained in:
Ben Gruver 2015-02-08 16:13:41 -08:00
parent 6649a75532
commit 4a9e7df53e
3 changed files with 78 additions and 39 deletions

View File

@ -39,8 +39,10 @@ import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.JavaCodeFragment; import com.intellij.psi.JavaCodeFragment;
import com.intellij.psi.JavaRecursiveElementVisitor; import com.intellij.psi.JavaRecursiveElementVisitor;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
@ -55,6 +57,7 @@ import org.jf.smalidea.psi.impl.SmaliInstruction;
import org.jf.smalidea.psi.impl.SmaliMethod; import org.jf.smalidea.psi.impl.SmaliMethod;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map; import java.util.Map;
public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory { public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory {
@ -185,10 +188,16 @@ public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory {
final JavaCodeFragment codeFragment = super.createCodeFragment(textWithImports, originalContext, project); final JavaCodeFragment codeFragment = super.createCodeFragment(textWithImports, originalContext, project);
codeFragment.accept(new JavaRecursiveElementVisitor() { codeFragment.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitLocalVariable(final PsiLocalVariable variable) { public void visitLocalVariable(final PsiLocalVariable variable) {
final String name = variable.getName(); final String name = variable.getName();
if (registerMap.containsKey(name)) { if (registerMap.containsKey(name)) {
debuggerContext.getDebugProcess().getManagerThread().invoke(new DebuggerCommandImpl() { DebugProcessImpl process = debuggerContext.getDebugProcess();
if (process == null) {
return;
}
process.getManagerThread().invoke(new DebuggerCommandImpl() {
@Override protected void action() throws Exception { @Override protected void action() throws Exception {
int registerNumber = Integer.parseInt(name.substring(1)); int registerNumber = Integer.parseInt(name.substring(1));
if (name.charAt(0) == 'p') { if (name.charAt(0) == 'p') {
@ -206,14 +215,10 @@ public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory {
variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, value); variable.putUserData(CodeFragmentFactoryContextWrapper.LABEL_VARIABLE_VALUE_KEY, value);
} }
}); });
} }
} }
}); });
int offset = variablesText.length() - 1; int offset = variablesText.length() - 1;
final PsiElement newContext = codeFragment.findElementAt(offset); final PsiElement newContext = codeFragment.findElementAt(offset);
@ -224,49 +229,61 @@ public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory {
} }
public Value evaluateRegister(EvaluationContextImpl context, final SmaliMethod smaliMethod, final int registerNum, public Value evaluateRegister(EvaluationContextImpl context, final SmaliMethod smaliMethod, final int registerNum,
final String type) { final String type) throws EvaluateException {
final StackFrameProxyImpl frameProxy = context.getFrameProxy(); final StackFrameProxyImpl frameProxy = context.getFrameProxy();
if (frameProxy == null) { if (frameProxy == null) {
return null; return null;
} }
// the jdi apis don't provide any way to get the value of an arbitrary register, so we use reflection // the jdi APIs don't provide any way to get the value of an arbitrary register, so we use reflection
// to create a LocalVariable instance for the register // to create a LocalVariable instance for the register
final Value[] ret = new Value[1];
DebugProcessImpl debugProcess = context.getDebugProcess(); VirtualMachine vm = frameProxy.getVirtualMachine().getVirtualMachine();
debugProcess.getManagerThread().invoke( Location currentLocation = frameProxy.location();
new DebuggerCommandImpl() { if (currentLocation == null) {
return null;
}
@Override protected void action() throws Exception { Method method = currentLocation.method();
VirtualMachine vm = frameProxy.getVirtualMachine().getVirtualMachine();
Method method = frameProxy.location().method();
final Constructor<LocalVariableImpl> localVariableConstructor = LocalVariableImpl.class.getDeclaredConstructor( try {
VirtualMachine.class, Method.class, Integer.TYPE, Location.class, Location.class, String.class, final Constructor<LocalVariableImpl> localVariableConstructor = LocalVariableImpl.class.getDeclaredConstructor(
String.class, String.class); VirtualMachine.class, Method.class, Integer.TYPE, Location.class, Location.class, String.class,
localVariableConstructor.setAccessible(true); String.class, String.class);
localVariableConstructor.setAccessible(true);
Constructor<LocationImpl> locationConstructor = LocationImpl.class.getDeclaredConstructor( Constructor<LocationImpl> locationConstructor = LocationImpl.class.getDeclaredConstructor(
VirtualMachine.class, Method.class, Long.TYPE); VirtualMachine.class, Method.class, Long.TYPE);
locationConstructor.setAccessible(true); locationConstructor.setAccessible(true);
// TODO: use frameProxy.location().method().locationOfCodeIndex() here // TODO: use frameProxy.location().method().locationOfCodeIndex() here
Location endLocation = locationConstructor.newInstance(vm, method, Integer.MAX_VALUE); Location endLocation = locationConstructor.newInstance(vm, method, Integer.MAX_VALUE);
LocalVariable localVariable = localVariableConstructor.newInstance(vm, LocalVariable localVariable = localVariableConstructor.newInstance(vm,
method, method,
mapRegisterForArt(smaliMethod, registerNum), mapRegister(frameProxy.getStackFrame().virtualMachine(), smaliMethod, registerNum),
frameProxy.location().method().locationOfCodeIndex(0), method.locationOfCodeIndex(0),
endLocation, endLocation,
String.format("v%d", registerNum), type, null); String.format("v%d", registerNum), type, null);
ret[0] = frameProxy.getStackFrame().getValue(localVariable); 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;
}
}
return ret[0]; private static int mapRegister(final VirtualMachine vm, final SmaliMethod smaliMethod, final int register) {
if (vm.version().equals("1.5.0")) {
return mapRegisterForDalvik(smaliMethod, register);
} else {
return mapRegisterForArt(smaliMethod, register);
}
} }
private static int mapRegisterForArt(final SmaliMethod smaliMethod, final int register) { private static int mapRegisterForArt(final SmaliMethod smaliMethod, final int register) {
@ -288,5 +305,27 @@ public class SmaliCodeFragmentFactory extends DefaultCodeFragmentFactory {
} }
}); });
} }
private static int mapRegisterForDalvik(final SmaliMethod smaliMethod, final int register) {
return ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
@Override public Integer compute() {
if (smaliMethod.getModifierList().hasModifierProperty("static")) {
return register;
}
int totalRegisters = smaliMethod.getRegisterCount();
int parameterRegisters = smaliMethod.getParameterRegisterCount();
// For dalvik, p0 is mapped to register 1, and register 0 is mapped to register 1000
if (register == (totalRegisters - parameterRegisters)) {
return 0;
}
if (register == 0) {
return 1000;
}
return register;
}
});
}
} }

View File

@ -40,16 +40,15 @@ import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
import com.sun.jdi.request.StepRequest; import com.sun.jdi.request.StepRequest;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
public class SmaliDebuggerSupport extends JavaDebuggerSupport { public class SmaliDebuggerSupport extends JavaDebuggerSupport {
private static boolean useModifiedMethod; private static boolean useModifiedMethod;
{ static {
try { try {
Method method = DebuggerSession.class.getMethod("stepOver", boolean.class, int.class); DebuggerSession.class.getMethod("stepOver", boolean.class, int.class);
useModifiedMethod = true; useModifiedMethod = true;
} catch (NoSuchMethodException ex) { } catch (NoSuchMethodException ex) {
useModifiedMethod = false;
} }
} }

View File

@ -34,10 +34,11 @@ package org.jf.smalidea.debugging;
import com.intellij.debugger.PositionManager; import com.intellij.debugger.PositionManager;
import com.intellij.debugger.PositionManagerFactory; import com.intellij.debugger.PositionManagerFactory;
import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.DebugProcess;
import org.jetbrains.annotations.NotNull;
public class SmaliPositionManagerFactory extends PositionManagerFactory { public class SmaliPositionManagerFactory extends PositionManagerFactory {
@Override @Override
public PositionManager createPositionManager(DebugProcess process) { public PositionManager createPositionManager(@NotNull DebugProcess process) {
return new SmaliPositionManager(process); return new SmaliPositionManager(process);
} }
} }