diff --git a/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs b/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs index 980b98c..19117a3 100644 --- a/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs +++ b/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs @@ -9,4 +9,5 @@ org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.7 diff --git a/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF b/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF index aab5e5a..6ada18c 100644 --- a/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF +++ b/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF @@ -3,13 +3,15 @@ Bundle-Name: DebuggingControl Bundle-SymbolicName: org.ntlab.reverseDebugger;singleton:=true Bundle-Version: 1.0.0.qualifier -Bundle-Activator: org.ntlab.debuggingControl.Activator +Bundle-Activator: org.ntlab.debuggingControl.ReverseDebuggerPlugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.debug.core, org.eclipse.jdt.debug, org.eclipse.jdt.core;bundle-version="3.10.2", org.eclipse.jdt.ui;bundle-version="3.10.2", - org.ntlab.traceAnalysisPlatform;bundle-version="1.0.0" + org.ntlab.traceAnalysisPlatform;bundle-version="1.0.0", + org.eclipse.ui.editors;bundle-version="3.11.100", + org.eclipse.jface.text;bundle-version="3.13.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy diff --git a/org.ntlab.reverseDebugger/plugin.xml b/org.ntlab.reverseDebugger/plugin.xml index f9ab0e4..f915beb 100644 --- a/org.ntlab.reverseDebugger/plugin.xml +++ b/org.ntlab.reverseDebugger/plugin.xml @@ -18,7 +18,7 @@ + + diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/Activator.java b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/Activator.java deleted file mode 100644 index e6910b9..0000000 --- a/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/Activator.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.ntlab.debuggingControl; - -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * The activator class controls the plug-in life cycle - */ -public class Activator extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "org.ntlab.helloWorld"; //$NON-NLS-1$ - - // The shared instance - private static Activator plugin; - - /** - * The constructor - */ - public Activator() { - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) - */ - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) - */ - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static Activator getDefault() { - return plugin; - } - -} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/ReverseDebuggerPlugin.java b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/ReverseDebuggerPlugin.java new file mode 100644 index 0000000..26dcdf9 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/ReverseDebuggerPlugin.java @@ -0,0 +1,49 @@ +package org.ntlab.debuggingControl; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class ReverseDebuggerPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.ntlab.helloWorld"; //$NON-NLS-1$ + + // The shared instance + private static ReverseDebuggerPlugin plugin; + + /** + * The constructor + */ + public ReverseDebuggerPlugin() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static ReverseDebuggerPlugin getDefault() { + return plugin; + } +} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIInstanceMethodCaller.java b/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIInstanceMethodCaller.java index 6b188da..ae279eb 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIInstanceMethodCaller.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIInstanceMethodCaller.java @@ -43,6 +43,6 @@ ClassType type = (ClassType)receiver.type(); List methodsByName = type.methodsByName(methodName); List argList = Arrays.asList(args); // ���\�b�h�ɓn�������̃��X�g - return receiver.invokeMethod(thread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED); // �f�o�b�O���̃v���O�������̃��\�b�h���Ăяo�� + return receiver.invokeMethod(onlineAnalysisThread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED); // �f�o�b�O���̃v���O�������̃��\�b�h���Ăяo�� } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIStaticMethodCaller.java b/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIStaticMethodCaller.java index 29d469e..311515a 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIStaticMethodCaller.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/onlineAccessor/JDIStaticMethodCaller.java @@ -19,11 +19,13 @@ @SuppressWarnings("restriction") public class JDIStaticMethodCaller { protected VirtualMachine vm; - protected ThreadReference thread; + protected ThreadReference targetThread; + protected static ThreadReference onlineAnalysisThread; public JDIStaticMethodCaller(VirtualMachine vm, ThreadReference thread) { this.vm = vm; - this.thread = thread; + this.targetThread = thread; +// this.targetThread = null; } public VirtualMachine getVm() { @@ -31,21 +33,30 @@ } public ThreadReference getThread() { - return thread; + return targetThread; +// return onlineAnalysisThread; } - + public long getThreadId() { - ClassType type = (ClassType)thread.type(); + ClassType type = (ClassType)targetThread.type(); List methodsByName = type.methodsByName("getId"); List argList = new ArrayList<>(); try { - return ((LongValue)thread.invokeMethod(thread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED)).value(); + return ((LongValue)targetThread.invokeMethod(onlineAnalysisThread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED)).value(); } catch (InvalidTypeException | ClassNotLoadedException | IncompatibleThreadStateException | InvocationException e) { e.printStackTrace(); } throw new IllegalStateException(); } + + public static ThreadReference getOnlineAnalysisThread() { + return onlineAnalysisThread; + } + + public static void setOnlineAnalysisThread(ThreadReference onlineAnalysisThread) { + JDIStaticMethodCaller.onlineAnalysisThread = onlineAnalysisThread; + } /** * �p�b�P�[�W���ƃN���X���ƃ��\�b�h���ƈ������w�肵�Ă��̃N���X���\�b�h���Ăяo�� @@ -67,12 +78,12 @@ List methodsByName = type.methodsByName("forName"); List argList = new ArrayList<>(); argList.add(vm.mirrorOf(fqcn)); - type.invokeMethod(thread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED); + type.invokeMethod(onlineAnalysisThread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED); classes = vm.classesByName(fqcn); // �N���X�� (���S����N���X��) } ClassType type = (ClassType)classes.get(0); List methodsByName = type.methodsByName(methodName); List argList = Arrays.asList(args); // ���\�b�h�ɓn�������̃��X�g - return type.invokeMethod(thread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED); // �f�o�b�O���̃v���O�������̃��\�b�h���Ăяo�� + return type.invokeMethod(onlineAnalysisThread, methodsByName.get(0), argList, ThreadReference.INVOKE_SINGLE_THREADED); // �f�o�b�O���̃v���O�������̃��\�b�h���Ăяo�� } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackLabelProvider.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackLabelProvider.java index 6f14937..da8a087 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackLabelProvider.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackLabelProvider.java @@ -13,14 +13,14 @@ public String getText(Object element) { if (element instanceof TreeNode) { Object value = ((TreeNode)element).getValue(); - if (value instanceof JDIStaticMethodCaller) { - JDIStaticMethodCaller mc = (JDIStaticMethodCaller)value; - return "ThreadID: " + mc.getThreadId(); + if (value instanceof String) { + String threadId = (String)value; + return "ThreadID: " + threadId; } if (value instanceof CallStackModel) { CallStackModel callStackModel = (CallStackModel)value; StringBuilder text = new StringBuilder(); - text.append(callStackModel.getSignature()); + text.append(callStackModel.getCallStackSignature()); text.append(" line: "); text.append(callStackModel.getCallLineNo()); return text.toString(); diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModel.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModel.java index 6eeccd0..b796011 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModel.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModel.java @@ -1,7 +1,9 @@ package org.ntlab.reverseDebugger; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; +import org.ntlab.traceAnalysisPlatform.tracer.trace.Trace; +import com.sun.jdi.BooleanValue; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.jdi.InvalidTypeException; @@ -15,9 +17,10 @@ @SuppressWarnings("restriction") public class CallStackModel { private JDIInstanceMethodCaller methodExecutionMc; + private String threadId; private int callLineNo; - public CallStackModel(VirtualMachine vm, ThreadReference thread, ObjectReference methodExecution, int callLineNo) { + public CallStackModel(VirtualMachine vm, ThreadReference thread, ObjectReference methodExecution, String threadId, int callLineNo) { methodExecutionMc = new JDIInstanceMethodCaller(vm, thread, methodExecution); this.callLineNo = callLineNo; } @@ -26,14 +29,14 @@ return methodExecutionMc.getVm(); } - public ThreadReference getThread() { - return methodExecutionMc.getThread(); - } - public JDIInstanceMethodCaller getMethodCaller() { return methodExecutionMc; } + public String getThreadId() { + return threadId; + } + public int getCallLineNo() { return callLineNo; } @@ -49,6 +52,32 @@ return signature; } + public String getCallStackSignature() { + String signature = ""; + try { + signature = getSignature(); + String objectType = ((StringReference)methodExecutionMc.callInstanceMethod("getThisClassName")).value(); + objectType = objectType.substring(objectType.lastIndexOf(".") + 1); + boolean isConstructor = ((BooleanValue)methodExecutionMc.callInstanceMethod("isConstructor")).value(); + String declaringType = Trace.getDeclaringType(signature, isConstructor); + declaringType = declaringType.substring(declaringType.lastIndexOf(".") + 1); + String methodName = Trace.getMethodName(signature); + String args = "(" + signature.split("\\(")[1]; + + StringBuilder sb = new StringBuilder(); + sb.append(objectType); + if (!declaringType.equals(objectType)) { + sb.append("(" + declaringType + ")"); + } + sb.append("." + methodName + args); + signature = sb.toString(); + } catch (InvalidTypeException | ClassNotLoadedException | InvocationException + | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + return signature; + } + public Value callInstanceMethod(String methodName, Value... args) throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { return methodExecutionMc.callInstanceMethod(methodName, args); diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModels.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModels.java index d516d6a..22571e6 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModels.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackModels.java @@ -1,60 +1,79 @@ package org.ntlab.reverseDebugger; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; - +import java.util.Map; import org.eclipse.jface.viewers.TreeNode; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; import org.ntlab.onlineAccessor.JDIStaticMethodCaller; - +import com.sun.jdi.BooleanValue; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.jdi.IntegerValue; import com.sun.jdi.InvalidTypeException; import com.sun.jdi.InvocationException; import com.sun.jdi.ObjectReference; +import com.sun.jdi.StringReference; import com.sun.jdi.ThreadReference; +import com.sun.jdi.Value; import com.sun.jdi.VirtualMachine; @SuppressWarnings("restriction") public class CallStackModels { - private List callStackModels = new ArrayList<>(); + private String debuggingThreadId = ""; + private List debuggingThreadCallStacks = new ArrayList<>(); + private Map> allCallStacks = new HashMap<>(); + private static final String TRACE = "org.ntlab.traceAnalysisPlatform.tracer.trace"; - public List getCallStackModels() { - return callStackModels; + public List getDebuggingThreadCallStacks() { + return debuggingThreadCallStacks; } - public TreeNode[] getCallStackModelsTreeNodes() { - TreeNode[] roots = new TreeNode[1]; - if (callStackModels.isEmpty()) { - return roots; + public TreeNode[] getAllCallStacksTree() { + TreeNode[] roots = new TreeNode[allCallStacks.size()]; + int rootIndex = 0; + for (String threadId : allCallStacks.keySet()) { + TreeNode node = getCallStackModelsTree(threadId); + roots[rootIndex++] = node; } - CallStackModel callStackModel = callStackModels.get(0); - roots[0] = new TreeNode(new JDIStaticMethodCaller(callStackModel.getVm(), callStackModel.getThread())); - TreeNode parentNode = roots[0]; - TreeNode[] childrenNode = new TreeNode[callStackModels.size()]; + return roots; + } + + public TreeNode getCallStackModelsTree(String threadId) { + List callStackModelsInThread = allCallStacks.get(threadId); + if (callStackModelsInThread.isEmpty()) return null; + TreeNode root = new TreeNode(threadId); + TreeNode parentNode = root; + TreeNode[] childrenNode = new TreeNode[callStackModelsInThread.size()]; parentNode.setChildren(childrenNode); - for (int i = 0; i < callStackModels.size(); i++) { - TreeNode childNode = new TreeNode(callStackModels.get(i)); + for (int i = 0; i < callStackModelsInThread.size(); i++) { + TreeNode childNode = new TreeNode(callStackModelsInThread.get(i)); childNode.setParent(parentNode); childrenNode[i] = childNode; } + return root; + } + + public TreeNode[] getDebugingThreadCallStacksTree() { + TreeNode[] roots = new TreeNode[1]; + roots[0] = getCallStackModelsTree(debuggingThreadId); return roots; } public void reset() { - callStackModels.clear(); + debuggingThreadId = ""; + debuggingThreadCallStacks.clear(); + allCallStacks.clear(); } public void updateByDebuggerStopMethodExecution(JDIInstanceMethodCaller me) { - if (me == null) { - return; - } + if (me == null) return; try { VirtualMachine vm = me.getVm(); ThreadReference thread = me.getThread(); int lineNo = thread.frame(0).location().lineNumber(); - update(vm, thread, me.getReceiver(), lineNo); + updateInAllThreads(vm, thread, me.getReceiver(), lineNo); } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); @@ -62,36 +81,148 @@ } public void updateByAlias(JDIInstanceMethodCaller alias) { - if (alias == null) { - return; - } + if (alias == null) return; VirtualMachine vm = alias.getVm(); ThreadReference thread = alias.getThread(); try { ObjectReference me = (ObjectReference)alias.callInstanceMethod("getMethodExecution"); int lineNo = ((IntegerValue)alias.callInstanceMethod("getLineNo")).value(); - update(vm, thread, me, lineNo); + updateInAllThreads(vm, thread, me, lineNo); } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); } } - - private void update(VirtualMachine vm, ThreadReference thread, ObjectReference me, int topMethodCallLineNo) + + private void updateInAllThreads(VirtualMachine vm, ThreadReference thread, ObjectReference me, int topMethodCallLineNo) throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { - callStackModels.clear(); - ObjectReference childMe = null; + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + mc.changeReceiver(me); + ObjectReference statements = (ObjectReference)mc.callInstanceMethod("getStatements"); + mc.changeReceiver(statements); + int lastIndex = ((IntegerValue)mc.callInstanceMethod("size")).value() - 1; + mc.changeReceiver(me); + ObjectReference tp = (ObjectReference)mc.callInstanceMethod("getTracePoint", vm.mirrorOf(lastIndex)); + mc.changeReceiver(tp); + ObjectReference tpStatement = (ObjectReference)mc.callInstanceMethod("getStatement"); + mc.changeReceiver(tpStatement); + + reset(); + debuggingThreadId = ((StringReference)mc.callInstanceMethod("getThreadNo")).value(); + debuggingThreadCallStacks = update(vm, thread, me, debuggingThreadId, topMethodCallLineNo); + allCallStacks.put(debuggingThreadId, debuggingThreadCallStacks); + Value visitor = getVisitor(vm, thread, tp); + updateOtherThreadCallStacks(vm, thread, visitor); + } + + private List update(VirtualMachine vm, ThreadReference thread, ObjectReference me, String threadId, int topMethodCallLineNo) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + List list = new ArrayList<>(); + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); int callLineNo = topMethodCallLineNo; - while (me != null) { - CallStackModel callStackModel = new CallStackModel(vm, thread, me, callLineNo); - callStackModels.add(callStackModel); - childMe = me; - me = (ObjectReference)callStackModel.callInstanceMethod("getParent"); - if (me != null) { - JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, me); + ObjectReference childMe = null; + ObjectReference tmpMe = me; + while (tmpMe != null) { + CallStackModel callStackModel = new CallStackModel(vm, thread, tmpMe, threadId, callLineNo); + list.add(callStackModel); + childMe = tmpMe; + tmpMe = (ObjectReference)callStackModel.callInstanceMethod("getParent"); + if (tmpMe != null) { + mc.changeReceiver(tmpMe); ObjectReference callStatement = (ObjectReference)mc.callInstanceMethod("getMethodInvocation", childMe); callLineNo = ((IntegerValue)mc.changeReceiver(callStatement).callInstanceMethod("getLineNo")).value(); } } - } -} + return list; + } + + private void updateOtherThreadCallStacks(VirtualMachine vm, ThreadReference thread, Value visitor) { + try { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + ObjectReference traceJSON = (ObjectReference)mc.callStaticMethod(TRACE, "TraceJSON", "getInstance"); + mc.changeReceiver(traceJSON); ObjectReference allThreads = (ObjectReference)mc.callInstanceMethod("getAllThreads"); + mc.changeReceiver(allThreads); ObjectReference keySet = (ObjectReference)mc.callInstanceMethod("keySet"); + mc.changeReceiver(keySet); ObjectReference iterator = (ObjectReference)mc.callInstanceMethod("iterator"); + mc.changeReceiver(iterator); boolean hasNext = ((BooleanValue)mc.callInstanceMethod("hasNext")).value(); + while (hasNext) { + StringReference threadId = (StringReference)mc.callInstanceMethod("next"); + if (threadId.value().equals(debuggingThreadId)) { + mc.changeReceiver(iterator); + hasNext = ((BooleanValue)mc.callInstanceMethod("hasNext")).value(); + continue; + } + + ObjectReference start = getStart(vm, thread, allThreads, threadId); + mc.changeReceiver(traceJSON); + mc.callInstanceMethod("getLastStatementInThread", threadId, start, visitor); + ObjectReference resultTp = (ObjectReference)mc.callStaticMethod("java.lang.reflect", "Array", "get", start, vm.mirrorOf(0)); + updateOtherThreadCallStacks(vm, thread, threadId.value(), resultTp); + + mc.changeReceiver(iterator); + hasNext = ((BooleanValue)mc.callInstanceMethod("hasNext")).value(); + } + } catch (InvalidTypeException | ClassNotLoadedException + | InvocationException | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + } + + private void updateOtherThreadCallStacks(VirtualMachine vm, ThreadReference thread, String threadId, ObjectReference tp) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + mc.changeReceiver(tp); + ObjectReference me = (ObjectReference)mc.callInstanceMethod("getMethodExecution"); + mc.changeReceiver(me); + ObjectReference statements = (ObjectReference)mc.callInstanceMethod("getStatements"); + mc.changeReceiver(statements); + int lastIndex = ((IntegerValue)mc.callInstanceMethod("size")).value() - 1; + ObjectReference lastStatement = (ObjectReference)mc.callInstanceMethod("get", vm.mirrorOf(lastIndex)); + mc.changeReceiver(lastStatement); + int lineNo = ((IntegerValue)mc.callInstanceMethod("getLineNo")).value(); + allCallStacks.put(threadId, update(vm, thread, me, threadId, lineNo)); + } + + private ObjectReference getVisitor(VirtualMachine vm, ThreadReference thread, ObjectReference tp) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + +// // visitor (�R���X�g���N�^�̈������Ȃ��ꍇ) +// ObjectReference clazz = (ObjectReference)mc.callStaticMethod( +// "java.lang", "Class", "forName", vm.mirrorOf("org.ntlab.reverseDebugger.CallStackVisitor")); +// mc.changeReceiver(clazz); +// ObjectReference visitor = (ObjectReference)mc.callInstanceMethod("newInstance"); + + // visitor (�R���X�g���N�^�Ɉ���������ꍇ) + ObjectReference visitorClass = (ObjectReference)mc.callStaticMethod( + "java.lang", "Class", "forName", vm.mirrorOf("org.ntlab.reverseDebugger.CallStackVisitor")); + ObjectReference classClass = (ObjectReference)mc.callStaticMethod( + "java.lang", "Class", "forName", vm.mirrorOf("java.lang.Class")); + ObjectReference classClassArray = (ObjectReference)mc.callStaticMethod("java.lang.reflect", "Array", "newInstance", classClass, vm.mirrorOf(1)); // �������•ϒ��̃��\�b�h��JDI�ŌĂяo���ۂ́A����1�‚ł��z��ɂ��Ȃ��ƃG���[���o�� + mc.changeReceiver(tp); + ObjectReference tpClass = (ObjectReference)mc.callInstanceMethod("getClass"); + mc.callStaticMethod("java.lang.reflect", "Array", "set", classClassArray, vm.mirrorOf(0), tpClass); + mc.changeReceiver(visitorClass); + ObjectReference constructor = (ObjectReference)mc.callInstanceMethod("getConstructor", classClassArray); + ObjectReference tpClassArray = (ObjectReference)mc.callStaticMethod("java.lang.reflect", "Array", "newInstance", tpClass, vm.mirrorOf(1)); // �������•ϒ��̃��\�b�h��JDI�ŌĂяo���ۂ́A����1�‚ł��z��ɂ��Ȃ��ƃG���[���o�� + mc.callStaticMethod("java.lang.reflect", "Array", "set", tpClassArray, vm.mirrorOf(0), tp); + mc.changeReceiver(constructor); + ObjectReference visitor = (ObjectReference)mc.callInstanceMethod("newInstance", tpClassArray); + return visitor; + } + + private ObjectReference getStart(VirtualMachine vm, ThreadReference thread, ObjectReference allThreads, StringReference threadId) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + + // start + mc.changeReceiver(allThreads); + ObjectReference threadInstance = (ObjectReference)mc.callInstanceMethod("get", threadId); + mc.changeReceiver(threadInstance); + ObjectReference currentTp = (ObjectReference)mc.callInstanceMethod("getCurrentTracePoint"); + mc.changeReceiver(currentTp); + ObjectReference currentTpClass = (ObjectReference)mc.callInstanceMethod("getClass"); + ObjectReference start = (ObjectReference)mc.callStaticMethod("java.lang.reflect", "Array", "newInstance", currentTpClass, vm.mirrorOf(1)); + mc.callStaticMethod("java.lang.reflect", "Array", "set", start, vm.mirrorOf(0), currentTp); + return start; + } +} \ No newline at end of file diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackView.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackView.java index 1fc480e..d0ac8a6 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackView.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackView.java @@ -12,14 +12,17 @@ import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; -public class CallStackView extends ViewPart { - private static TreeViewer viewer; +public class CallStackView extends ViewPart { + private TreeViewer viewer; private IAction refreshAction; - private static CallStackModels callStackModels = new CallStackModels(); + private CallStackModels callStackModels = new CallStackModels(); private JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); public static final String ID = "org.ntlab.reverseDebugger.callStackView"; @@ -46,10 +49,12 @@ if (element instanceof TreeNode) { Object value = ((TreeNode)element).getValue(); if (value instanceof CallStackModel) { - JDIInstanceMethodCaller methodExecution = ((CallStackModel)value).getMethodCaller(); - SeedAliasView.createSeedAliasesByMethodExecution(methodExecution); - SeedAliasView.refresh(); - javaEditorOperator.openSrcFileOfMethodExecution(methodExecution); + CallStackModel callStackModel = (CallStackModel)value; + JDIInstanceMethodCaller methodExecution = callStackModel.getMethodCaller(); + SeedAliasView seedAliasView = ((SeedAliasView)getOtherView(SeedAliasView.ID)); + seedAliasView.createSeedAliasesByMethodExecution(methodExecution); + seedAliasView.refresh(); + javaEditorOperator.openSrcFileOfMethodExecution(methodExecution, callStackModel.getCallLineNo()); } } } @@ -87,16 +92,17 @@ mgr.add(refreshAction); } - public static void updateByAlias(JDIInstanceMethodCaller alias) { + public void updateByAlias(JDIInstanceMethodCaller alias) { callStackModels.updateByAlias(alias); } - public static void refresh() { - if (callStackModels.getCallStackModels().isEmpty()) { - JDIInstanceMethodCaller currentMe = SeedAliasView.getDebuggerStopMethodExecution(); + public void refresh() { + if (callStackModels.getDebuggingThreadCallStacks().isEmpty()) { + SeedAliasView seedAliasView = ((SeedAliasView)getOtherView(SeedAliasView.ID)); + JDIInstanceMethodCaller currentMe = seedAliasView.getDebuggingMethodExecution(); callStackModels.updateByDebuggerStopMethodExecution(currentMe); } - TreeNode[] nodes = callStackModels.getCallStackModelsTreeNodes(); + TreeNode[] nodes = callStackModels.getAllCallStacksTree(); if (nodes == null || nodes[0] == null) { return; } @@ -104,8 +110,17 @@ viewer.expandAll(); } - public static void reset() { + public void reset() { callStackModels.reset(); refresh(); } + + private IViewPart getOtherView(String viewId) { + IWorkbenchPage workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + return workbenchPage.showView(viewId); + } catch (PartInitException e) { + throw new RuntimeException(e); + } + } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackVisitor.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackVisitor.java new file mode 100644 index 0000000..605a664 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/CallStackVisitor.java @@ -0,0 +1,32 @@ +package org.ntlab.reverseDebugger; + +import org.ntlab.traceAnalysisPlatform.tracer.trace.IStatementVisitor; +import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodInvocation; +import org.ntlab.traceAnalysisPlatform.tracer.trace.Statement; +import org.ntlab.traceAnalysisPlatform.tracer.trace.TracePoint; + +public class CallStackVisitor implements IStatementVisitor { + private TracePoint before = null; + + public CallStackVisitor() { + + } + + public CallStackVisitor(TracePoint before) { + this.before = before; + } + + @Override + public boolean preVisitStatement(Statement statement) { + System.out.println("CallStackVisitor#preVisitStatement(Statement)"); + if (!(statement instanceof MethodInvocation)) return false; + if (before == null) return true; + MethodInvocation mi = (MethodInvocation)statement; + return (mi.getTimeStamp() < before.getStatement().getTimeStamp()); + } + + @Override + public boolean postVisitStatement(Statement statement) { + return false; + } +} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java index 2927341..a4c4dd9 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java @@ -14,12 +14,20 @@ import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.ui.JavaUI; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.IncompatibleThreadStateException; +import com.sun.jdi.IntegerValue; import com.sun.jdi.InvalidTypeException; import com.sun.jdi.InvocationException; import com.sun.jdi.ObjectReference; @@ -33,7 +41,8 @@ try { ObjectReference methodExecution = (ObjectReference)alias.callInstanceMethod("getMethodExecution"); JDIInstanceMethodCaller meCaller = new JDIInstanceMethodCaller(alias.getVm(), alias.getThread(), methodExecution); - openSrcFileOfMethodExecution(meCaller); + int lineNo = ((IntegerValue)alias.callInstanceMethod("getLineNo")).value(); + openSrcFileOfMethodExecution(meCaller, lineNo); } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); @@ -44,16 +53,16 @@ * �����œn����meCaller���ɂ���methodExecution����`����Ă���N���X�̃\�[�X�R�[�h��Ώ�Eclipse�̃G�f�B�^�ŊJ������ * * @param meCaller + * @param highlightLineNo */ - public void openSrcFileOfMethodExecution(JDIInstanceMethodCaller meCaller) { + public void openSrcFileOfMethodExecution(JDIInstanceMethodCaller meCaller, int highlightLineNo) { try { IType type = findIType(meCaller); if (type != null) { IMethod method = findIMethod(meCaller, type); - if (method != null) { - openSrcFileOfIMethod(type, method); - } - } + openSrcFile(type, method); + highlight(highlightLineNo); + } } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); @@ -66,27 +75,54 @@ * @param type * @param method */ - private void openSrcFileOfIMethod(IType type, IMethod method) throws InvalidTypeException, ClassNotLoadedException, + private void openSrcFile(IType type, IMethod method) throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { openInJavaEditor(type, method); } - private IType findIType(JDIInstanceMethodCaller meCaller) throws InvalidTypeException, + /** + * ���݃G�f�B�^�ŊJ����Ă���t�@�C���̎w�肵���s�Ƀn�C���C�g�������� + * @param lineNo �n�C���C�g��������s�� + */ + public void highlight(int lineNo) { + if (lineNo < 1) return; + IWorkbench workbench = PlatformUI.getWorkbench(); + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IEditorPart editorPart = window.getActivePage().getActiveEditor(); + if (editorPart instanceof ITextEditor) { + ITextEditor editor = (ITextEditor)editorPart; + IDocumentProvider provider = editor.getDocumentProvider(); + IDocument document = provider.getDocument(editor.getEditorInput()); + try { + editor.selectAndReveal(document.getLineOffset(lineNo - 1), document.getLineLength(lineNo - 1)); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + public IType findIType(JDIInstanceMethodCaller meCaller) throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { - StringReference declaringClassName = (StringReference)meCaller.callInstanceMethod("getDeclaringClassName"); - String projectPath = getLoaderPath(meCaller, declaringClassName); + String declaringClassName = ((StringReference)meCaller.callInstanceMethod("getDeclaringClassName")).value(); + declaringClassName = declaringClassName.replace(".", ""); + return findIType(meCaller, declaringClassName); + } + + public IType findIType(JDIInstanceMethodCaller mc, String declaringClassName) throws InvalidTypeException, + ClassNotLoadedException, InvocationException, IncompatibleThreadStateException{ + String projectPath = getLoaderPath(mc, mc.getVm().mirrorOf(declaringClassName)); IType type = null; if (projectPath != null) { IJavaProject javaProject = findJavaProject(projectPath); if (javaProject != null) { try { - type = javaProject.findType(declaringClassName.value()); + type = javaProject.findType(declaringClassName); } catch (JavaModelException e) { e.printStackTrace(); } } } - return type; + return type; } private String getLoaderPath(JDIInstanceMethodCaller meCaller, StringReference declaringClassName) @@ -94,7 +130,7 @@ ObjectReference getInstance = (ObjectReference)meCaller.callStaticMethod(TRACE, "TraceJSON", "getInstance"); JDIInstanceMethodCaller traceInstanceCaller = new JDIInstanceMethodCaller(meCaller.getVm(), meCaller.getThread(), getInstance); ObjectReference classInfo = (ObjectReference)traceInstanceCaller.callInstanceMethod("getClassInfo", declaringClassName); - if (classInfo == null) { + if (classInfo == null && meCaller.getReceiver() != null) { declaringClassName = (StringReference)meCaller.callInstanceMethod("getThisClassName"); classInfo = (ObjectReference)traceInstanceCaller.callInstanceMethod("getClassInfo", declaringClassName); } @@ -104,7 +140,7 @@ JDIInstanceMethodCaller classInfoMethodCaller = new JDIInstanceMethodCaller(meCaller.getVm(), meCaller.getThread(), classInfo); String path = ((StringReference)classInfoMethodCaller.callInstanceMethod("getPath")).value(); String declaringClassNameString = declaringClassName.value().replace(".", "/"); - loaderPath = path.substring(0, path.indexOf(declaringClassNameString)); // path����N���X�̊��S���薼�ȍ~��S�ĊO�������̂�projectPath�ɂ��Ă݂� + loaderPath = path.substring(0, path.lastIndexOf(declaringClassNameString)); // path����N���X�̊��S���薼�ȍ~��S�ĊO�������̂�projectPath�ɂ��Ă݂� } return loaderPath; } @@ -133,10 +169,14 @@ private void openInJavaEditor(IType type, IMethod method) { try { - if (type != null && method != null) { + if (type != null) { IEditorPart editor = JavaUI.openInEditor(type); if (!type.isLocal() && !type.isMember()) { - JavaUI.revealInEditor(editor, (IJavaElement) method); + if (method != null) { + JavaUI.revealInEditor(editor, (IJavaElement)method); + } else { + JavaUI.revealInEditor(editor, (IJavaElement)type); + } } } } catch (PartInitException | JavaModelException e) { @@ -154,7 +194,7 @@ return method; } - private IMethod findIMethod(IType type, String methodSignature) { + public IMethod findIMethod(IType type, String methodSignature) { try { for (IMethod method : type.getMethods()) { if (checkMethodSignature(type, method, methodSignature)) { diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasLabelProvider.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasLabelProvider.java index 40f3a22..4dc3f5f 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasLabelProvider.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasLabelProvider.java @@ -31,7 +31,7 @@ case 1: return ((StringReference)mc.callInstanceMethod("getClassName")).value(); case 2: - return ((StringReference)mc.callInstanceMethod("getMethodExecutionClassName")).value(); + return ((StringReference)mc.callInstanceMethod("getSourceFileName")).value(); case 3: return String.valueOf(((IntegerValue)mc.callInstanceMethod("getLineNo")).value()); case 4: diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasView.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasView.java index b00a98f..0c28d4d 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasView.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliasView.java @@ -18,17 +18,20 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; public class ObjectFlowAliasView extends ViewPart { - private static TableViewer viewer; + private TableViewer viewer; private IAction refreshAction; private IAction findSeedAliasesAction; private JDIInstanceMethodCaller selectObjectFlowAlias; - private static ObjectFlowAliases objectFlowAliases = new ObjectFlowAliases(); + private ObjectFlowAliases objectFlowAliases = new ObjectFlowAliases(); private JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); public static final String ID = "org.ntlab.reverseDebugger.objectFlowAliasView"; @@ -151,26 +154,37 @@ getSite().registerContextMenu(menuMgr, viewer); } - public static void createObjectFlow(JDIInstanceMethodCaller seedAlias) { + public void createObjectFlow(JDIInstanceMethodCaller seedAlias) { objectFlowAliases.createObjectFlow(seedAlias); } private void findSeedAliases() { if (selectObjectFlowAlias != null) { - SeedAliasView.createSeedAliasesByAlias(selectObjectFlowAlias); - SeedAliasView.refresh(); - CallStackView.updateByAlias(selectObjectFlowAlias); - CallStackView.refresh(); + SeedAliasView seedAliasView = ((SeedAliasView)getOtherView(SeedAliasView.ID)); + seedAliasView.createSeedAliasesByAlias(selectObjectFlowAlias); + seedAliasView.refresh(); + CallStackView callStackView = ((CallStackView)getOtherView(CallStackView.ID)); + callStackView.updateByAlias(selectObjectFlowAlias); + callStackView.refresh(); javaEditorOperator.openSrcFileOfAlias(selectObjectFlowAlias); } } - public static void refresh() { + public void refresh() { viewer.setInput(objectFlowAliases.getObjectFlowSingleList(true)); } - public static void reset() { + public void reset() { objectFlowAliases.reset(); viewer.setInput(objectFlowAliases.getObjectFlowSingleList(true)); } + + private IViewPart getOtherView(String viewId) { + IWorkbenchPage workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + return workbenchPage.showView(viewId); + } catch (PartInitException e) { + throw new RuntimeException(e); + } + } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliases.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliases.java index 9cea0fa..0905a78 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliases.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ObjectFlowAliases.java @@ -52,7 +52,7 @@ objectFlowAliases.clear(); try { // �I�������G�C���A�X���N�_�ɃI�u�W�F�N�g�t���[���Ăяo���Č��ʂ����X�g�Ŏ󂯎�� - ObjectReference aliasListsReference = (ObjectReference)seedAlias.callStaticMethod(ReverseDebuggerLaunchConfiguration.ANALYZER_PACKAGE, ReverseDebuggerLaunchConfiguration.ANALYZER_CLASS, "getObjectFlow", seedAlias.getReceiver()); + ObjectReference aliasListsReference = (ObjectReference)seedAlias.callStaticMethod(ReverseDebuggerLaunchConfiguration.ANALYZER_PACKAGE, ReverseDebuggerLaunchConfiguration.ANALYZER_CLASS, "getObjectFlowStatic", seedAlias.getReceiver()); // �擾�������X�g�̒��g�����[�v�ʼn񂵂Ȃ�����o��, �Ǘ��p�̃��X�g�ɋl�ߒ��� JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(seedAlias.getVm(), seedAlias.getThread(), aliasListsReference); diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java index 6eb0664..405f846 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java @@ -21,6 +21,10 @@ // �E���ɃI�u�W�F�N�g�t���[�G�C���A�X�̃r���[��z�u IFolderLayout bottomRight = layout.createFolder("bottomRight", IPageLayout.RIGHT, 0.5f, editorArea); - bottomRight.addView(ObjectFlowAliasView.ID); + bottomRight.addView(ObjectFlowAliasView.ID); + + // �E��ɕϐ��̃r���[��z�u + IFolderLayout topRight2 = layout.createFolder("topRight2", IPageLayout.RIGHT, 0.5f, "topLeft"); + topRight2.addView(VariableView.ID); } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasLabelProvider.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasLabelProvider.java index 0f146df..5917593 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasLabelProvider.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasLabelProvider.java @@ -28,7 +28,7 @@ case 1: return ((StringReference)mc.callInstanceMethod("getClassName")).value(); case 2: - return ((StringReference)mc.callInstanceMethod("getMethodExecutionClassName")).value(); + return ((StringReference)mc.callInstanceMethod("getSourceFileName")).value(); case 3: return String.valueOf(((IntegerValue)mc.callInstanceMethod("getLineNo")).value()); case 4: diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java index 15ff709..56f18da 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java @@ -18,19 +18,22 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; -public class SeedAliasView extends ViewPart { - private static TableViewer viewer; +public class SeedAliasView extends ViewPart { + private TableViewer viewer; private IAction refreshAction; private IAction resetAction; private IAction getObjectFlowAction; private JDIInstanceMethodCaller selectSeedAlias; - private static SeedAliases seedAliases = new SeedAliases(); - private static JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); + private SeedAliases seedAliases = new SeedAliases(); + private JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); public static final String ID = "org.ntlab.reverseDebugger.seedAliasView"; public SeedAliasView() { @@ -59,7 +62,7 @@ viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new SeedAliasLabelProvider()); viewer.setInput(seedAliases.getSeedAliases()); - CallStackView.refresh(); + ((CallStackView)getOtherView(CallStackView.ID)).refresh(); // �I�������J�����ɑΉ�����V�[�h�G�C���A�X���t�B�[���h�ɋL�^���Ă������X�i�[��o�^ (�I��������ɉE�N���b�N�ŃI�u�W�F�N�g�t���[�����s������ۂɕK�v) viewer.addSelectionChangedListener(new ISelectionChangedListener() { @@ -69,6 +72,7 @@ Object element = sel.getFirstElement(); if (element instanceof JDIInstanceMethodCaller) { selectSeedAlias = (JDIInstanceMethodCaller)element; + ((VariableView)getOtherView(VariableView.ID)).updateVariablesByAlias(selectSeedAlias); javaEditorOperator.openSrcFileOfAlias(selectSeedAlias); } } @@ -145,37 +149,56 @@ getSite().registerContextMenu(menuMgr, viewer); } - public static JDIInstanceMethodCaller getDebuggerStopMethodExecution() { - return seedAliases.getDebuggerStopMethodExecution(); + public JDIInstanceMethodCaller getDebuggingMethodExecution() { + return seedAliases.getDebuggingMethodExecution(); } - public static void createSeedAliasesByAlias(JDIInstanceMethodCaller alias) { + public void createSeedAliasesByAlias(JDIInstanceMethodCaller alias) { seedAliases.createSeedAliasesByAlias(alias); + ((VariableView)getOtherView(VariableView.ID)).updateVariablesByAlias(alias); } - public static void createSeedAliasesByMethodExecution(JDIInstanceMethodCaller methodExecution) { + public void createSeedAliasesByMethodExecution(JDIInstanceMethodCaller methodExecution) { seedAliases.createSeedAliasesByMethodExecution(methodExecution); + ((VariableView)getOtherView(VariableView.ID)).updateVariablesByMethodExecution(methodExecution); } - public static void refresh() { + public void refresh() { if (seedAliases.getSeedAliases().isEmpty()) { seedAliases.initSeedAliases(); - javaEditorOperator.openSrcFileOfMethodExecution(seedAliases.getDebuggerStopMethodExecution()); - CallStackView.reset(); + JDIInstanceMethodCaller debuggingMethodExecution = seedAliases.getDebuggingMethodExecution(); + int debuggingLineNo = seedAliases.getDebuggingLineNo(); + javaEditorOperator.openSrcFileOfMethodExecution(debuggingMethodExecution, debuggingLineNo); + ((CallStackView)getOtherView(CallStackView.ID)).reset(); + ((VariableView)getOtherView(VariableView.ID)).updateVariablesByMethodExecution(debuggingMethodExecution); } viewer.refresh(); } private void reset() { seedAliases.reset(); - ObjectFlowAliasView.reset(); + ((ObjectFlowAliasView)getOtherView(ObjectFlowAliasView.ID)).reset(); refresh(); } private void getObjectFlow() { if (selectSeedAlias != null) { - ObjectFlowAliasView.createObjectFlow(selectSeedAlias); - ObjectFlowAliasView.refresh(); + ObjectFlowAliasView objectFlowAliasView = ((ObjectFlowAliasView)getOtherView(ObjectFlowAliasView.ID)); + objectFlowAliasView.createObjectFlow(selectSeedAlias); + objectFlowAliasView.refresh(); } } + + public JDIInstanceMethodCaller getSelectSeedAlias() { + return selectSeedAlias; + } + + private IViewPart getOtherView(String viewId) { + IWorkbenchPage workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + return workbenchPage.showView(viewId); + } catch (PartInitException e) { + throw new RuntimeException(e); + } + } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java index e88f45a..96963c2 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java @@ -5,6 +5,7 @@ import org.ntlab.onlineAccessor.JDIDebuggingVirtualMachine; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; +import org.ntlab.onlineAccessor.JDIStaticMethodCaller; import org.ntlab.onlineAccessor.NotDebuggedException; import org.ntlab.onlineAccessor.NotExecutedException; import org.ntlab.onlineAccessor.NotSuspendedException; @@ -24,7 +25,7 @@ @SuppressWarnings("restriction") public class SeedAliases { - private JDIInstanceMethodCaller debuggerStopMethodExecution = null; + private JDIInstanceMethodCaller debuggingMethodExecution = null; private List seedAliases = new ArrayList<>(); private static final String TRACER = "org.ntlab.traceAnalysisPlatform.tracer.trace"; @@ -32,8 +33,17 @@ initSeedAliases(); } - public JDIInstanceMethodCaller getDebuggerStopMethodExecution() { - return debuggerStopMethodExecution; + public JDIInstanceMethodCaller getDebuggingMethodExecution() { + return debuggingMethodExecution; + } + + public int getDebuggingLineNo() { + try { + ThreadReference thread = debuggingMethodExecution.getThread(); + return thread.frame(0).location().lineNumber(); + } catch (IncompatibleThreadStateException e) { + throw new RuntimeException(e); + } } public List getSeedAliases() { @@ -43,42 +53,68 @@ public void reset() { seedAliases.clear(); } - + public void initSeedAliases() { try { VirtualMachine vm = JDIDebuggingVirtualMachine.getDebuggineVirtualMachine(); List allThreads = vm.allThreads(); + ThreadReference onlineAnalysisThread = null; + ThreadReference targetThread = null; for (int i = 0; i < allThreads.size(); i++) { ThreadReference thread = allThreads.get(i); - if (thread.isSuspended() && !(thread.name().equals("OnlineAnalysisThread"))) { - createSeedAliases(vm, thread); + if (thread.isSuspended()) { + if (thread.name().equals("OnlineAnalysisThread")) { + onlineAnalysisThread = thread; + JDIStaticMethodCaller.setOnlineAnalysisThread(onlineAnalysisThread); + } else if (targetThread == null) { + targetThread = thread; + } } - } - } catch (NotExecutedException | NotSuspendedException - | NotDebuggedException e) { + if (onlineAnalysisThread != null && targetThread != null) { + System.out.println("createSeedAliases"); + createSeedAliases(vm, targetThread); + break; + } + } + } catch (NotExecutedException | NotSuspendedException | NotDebuggedException e) { e.printStackTrace(); } } + +// public void initSeedAliases() { +// try { +// VirtualMachine vm = JDIDebuggingVirtualMachine.getDebuggineVirtualMachine(); +// List allThreads = vm.allThreads(); +// for (int i = 0; i < allThreads.size(); i++) { +// ThreadReference thread = allThreads.get(i); +// if (thread.isSuspended() && !(thread.name().equals("OnlineAnalysisThread"))) { +// createSeedAliases(vm, thread); +// } +// } +// } catch (NotExecutedException | NotSuspendedException | NotDebuggedException e) { +// e.printStackTrace(); +// } +// } /** * ���݃f�o�b�K�Ŏ~�܂��Ă���n�_�ł̃��\�b�h���s���̑S�V�[�h�G�C���A�X�ꗗ���Z�b�g���� * @param vm - * @param thread + * @param onlineAnalysisThread */ private void createSeedAliases(VirtualMachine vm, ThreadReference thread) { JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, thread); try { // threadId�̎擾��StringReference�^�ւ̕ϊ� -// Value threadIdValue = mc.changeReceiver(thread).callInstanceMethod("getId"); - Value threadIdValue = vm.mirrorOf(mc.getThreadId()); - StringReference threadId = vm.mirrorOf(String.valueOf(((LongValue)threadIdValue).value())); + long threadIdValue = ((LongValue)mc.callInstanceMethod("getId")).value(); + StringReference threadId = vm.mirrorOf(String.valueOf(threadIdValue)); // threadId�ɑΉ�����ThreadInstance���擾 ObjectReference threadInstance = (ObjectReference)mc.callStaticMethod(TRACER, "TraceJSON", "getThreadInstance", threadId); Value methodExecution = mc.changeReceiver(threadInstance).callInstanceMethod("getCurrentMethodExecution"); - debuggerStopMethodExecution = new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution); + debuggingMethodExecution = new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution); findAllSeedAlias(vm, thread, methodExecution); - } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { + } catch (InvalidTypeException | ClassNotLoadedException + | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); } } @@ -122,7 +158,7 @@ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); seedAliases.clear(); - ObjectReference seedAliasList = (ObjectReference)mc.callStaticMethod(ReverseDebuggerLaunchConfiguration.ANALYZER_PACKAGE, ReverseDebuggerLaunchConfiguration.ANALYZER_CLASS, "findAllSeedAliases", methodExecution); + ObjectReference seedAliasList = (ObjectReference)mc.callStaticMethod(ReverseDebuggerLaunchConfiguration.ANALYZER_PACKAGE, ReverseDebuggerLaunchConfiguration.ANALYZER_CLASS, "findAllSeedAliasesStatic", methodExecution); int seedAliasListSize = ((IntegerValue)mc.changeReceiver(seedAliasList).callInstanceMethod("size")).value(); for (int i = 0; i < seedAliasListSize; i++) { ObjectReference seedAlias = (ObjectReference)mc.changeReceiver(seedAliasList).callInstanceMethod("get", vm.mirrorOf(i)); diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableLabelProvider.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableLabelProvider.java new file mode 100644 index 0000000..f8c9570 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableLabelProvider.java @@ -0,0 +1,43 @@ +package org.ntlab.reverseDebugger; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeNode; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +public class VariableLabelProvider extends LabelProvider implements ITableLabelProvider { + @Override + public String getColumnText(Object element, int columnIndex) { + if (element instanceof TreeNode) { + Object value = ((TreeNode)element).getValue(); + if (value instanceof VariableData) { + VariableData variableData = (VariableData)value; + switch (columnIndex) { + case 0: + String variableName = variableData.getVariableName(); + if (variableName.contains("[")) { + return variableName.substring(variableName.lastIndexOf("[")); + } else if (variableName.contains(".")) { + return variableName.substring(variableName.lastIndexOf(".") + 1); + } + return variableName; + case 1: + return variableData.getClassName() + " (" + "id = " + variableData.getId() + ")"; + } + } + } + return "�e�X�g�p�e�L�X�g" + columnIndex; + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return getImage(element); + } + + @Override + public Image getImage(Object element) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT); + } +} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableView.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableView.java new file mode 100644 index 0000000..03ca045 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableView.java @@ -0,0 +1,133 @@ +package org.ntlab.reverseDebugger; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.viewers.TreeNodeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; +import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; + +public class VariableView extends ViewPart { + private TreeViewer viewer; +// private IAction refreshAction; +// private IAction resetAction; + private Variables variables = new Variables(); + public static final String ID = "org.ntlab.reverseDebugger.variableView"; + + public VariableView() { + // TODO Auto-generated constructor stub + System.out.println("VariableView�N���X���������ꂽ��!"); + } + + @Override + public void createPartControl(Composite parent) { + // TODO Auto-generated method stub + System.out.println("VariableView#createPartControl(Composite)���Ă΂ꂽ��!"); + viewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + Tree tree = viewer.getTree(); + tree.setHeaderVisible(true); + tree.setLinesVisible(true); + + String[] treeColumnTexts = {"Name", "Value"}; + int[] treeColumnWidth = {100, 200}; + TreeColumn[] treeColumns = new TreeColumn[treeColumnTexts.length]; + for (int i = 0; i < treeColumns.length; i++) { + treeColumns[i] = new TreeColumn(tree, SWT.NULL); + treeColumns[i].setText(treeColumnTexts[i]); + treeColumns[i].setWidth(treeColumnWidth[i]); + } + viewer.setContentProvider(new TreeNodeContentProvider()); + viewer.setLabelProvider(new VariableLabelProvider()); + SeedAliasView seedAliasView = ((SeedAliasView)getOtherView(SeedAliasView.ID)); + JDIInstanceMethodCaller methodExecution = seedAliasView.getDebuggingMethodExecution(); + if (methodExecution != null) { + variables.getAllObjectDataByMethodExecution(methodExecution); + viewer.setInput(variables.getVariablesTreeNodes()); + } + createActions(); + createToolBar(); + createMenuBar(); + } + + @Override + public void setFocus() { + // TODO Auto-generated method stub + viewer.getControl().setFocus(); + } + + private void createActions() { +// refreshAction = new Action() { +// @Override +// public void run() { +// refresh(); +// } +// }; +// refreshAction.setText("refresh"); +// refreshAction.setToolTipText("refresh"); +// refreshAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_ELCL_SYNCED)); +// +// resetAction = new Action() { +// @Override +// public void run() { +// reset(); +// } +// }; +// resetAction.setText("reset"); +// resetAction.setToolTipText("reset"); +// resetAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_ETOOL_HOME_NAV)); + } + + private void createToolBar() { + IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager(); +// mgr.add(refreshAction); +// mgr.add(resetAction); + } + + private void createMenuBar() { + IMenuManager mgr = getViewSite().getActionBars().getMenuManager(); +// mgr.add(refreshAction); +// mgr.add(resetAction); + } + +// public static void refresh() { +// selectedAlias = SeedAliasView.getSelectSeedAlias(); +// if (selectedAlias != null) { +// variables.getAllObjectDataByAlias(selectedAlias); +// viewer.setInput(variables.getVariablesTreeNodes()); +// } +// } + +// private void reset() { +// selectedAlias = SeedAliasView.getSelectSeedAlias(); +// if (selectedAlias != null) { +// updateVariablesByAlias(selectedAlias); +// } +// } + + public void updateVariablesByMethodExecution(JDIInstanceMethodCaller methodExecution) { + variables.getAllObjectDataByMethodExecution(methodExecution); + viewer.setInput(variables.getVariablesTreeNodes()); + } + + public void updateVariablesByAlias(JDIInstanceMethodCaller alias) { + variables.getAllObjectDataByAlias(alias); + viewer.setInput(variables.getVariablesTreeNodes()); + } + + private IViewPart getOtherView(String viewId) { + IWorkbenchPage workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + return workbenchPage.showView(viewId); + } catch (PartInitException e) { + throw new RuntimeException(e); + } + } +} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/Variables.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/Variables.java new file mode 100644 index 0000000..18dc2e7 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/Variables.java @@ -0,0 +1,343 @@ +package org.ntlab.reverseDebugger; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.core.Flags; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jface.viewers.TreeNode; +import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; +import com.sun.jdi.ClassNotLoadedException; +import com.sun.jdi.ClassType; +import com.sun.jdi.Field; +import com.sun.jdi.IncompatibleThreadStateException; +import com.sun.jdi.IntegerValue; +import com.sun.jdi.InvalidTypeException; +import com.sun.jdi.InvocationException; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.StringReference; +import com.sun.jdi.ThreadReference; +import com.sun.jdi.Value; +import com.sun.jdi.VirtualMachine; + +public class Variables { + private VariableData rootThisObjData; + private List argsData = new ArrayList<>(); + private List allObjData = new ArrayList<>(); + private static final String TRACER = "org.ntlab.traceAnalysisPlatform.tracer.trace"; + + public TreeNode[] getVariablesTreeNodes() { + TreeNode[] roots = new TreeNode[allObjData.size()]; + if (allObjData.isEmpty()) { + return roots; + } + for (int i = 0; i < allObjData.size(); i++) { + VariableData rootVariableData = allObjData.get(i); + createVariablesTreeNode(null, roots, i, rootVariableData); + } + return roots; + } + + private void createVariablesTreeNode(TreeNode parentNode, TreeNode[] addingNodes, int index, VariableData addingVariableData) { + TreeNode newNode = new TreeNode(addingVariableData); + newNode.setParent(parentNode); + addingNodes[index] = newNode; + TreeNode[] childNodes = new TreeNode[addingVariableData.getChildren().size()]; + addingNodes[index].setChildren(childNodes); + for (int i = 0; i < addingVariableData.getChildren().size(); i++) { + VariableData child = addingVariableData.getChildren().get(i); + createVariablesTreeNode(newNode, childNodes, i, child); + } + } + + public List getAllObjectDataByMethodExecution(JDIInstanceMethodCaller methodExecution) { + if (methodExecution == null) return new ArrayList<>(); + try { + VirtualMachine vm = methodExecution.getVm(); + ThreadReference thread = methodExecution.getThread(); + ObjectReference method = methodExecution.getReceiver(); + + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, method); + ObjectReference statements = (ObjectReference)mc.callInstanceMethod("getStatements"); + mc.changeReceiver(statements); + int lastOrder = ((IntegerValue)mc.callInstanceMethod("size")).value() - 1; + mc.changeReceiver(method); + ObjectReference tp = (ObjectReference)mc.callInstanceMethod("getTracePoint", vm.mirrorOf(lastOrder)); + + getAllObjectData(vm, thread, method, tp); + } catch (InvalidTypeException | ClassNotLoadedException + | InvocationException | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + return allObjData; + } + + public List getAllObjectDataByAlias(JDIInstanceMethodCaller alias) { + if (alias == null) return new ArrayList<>(); + try { + VirtualMachine vm = alias.getVm(); + ThreadReference thread = alias.getThread(); + ObjectReference methodExecution = (ObjectReference)alias.callInstanceMethod("getMethodExecution"); + ObjectReference tp = (ObjectReference)alias.callInstanceMethod("getOccurrencePoint"); + getAllObjectData(vm, thread, methodExecution, tp); + } catch (InvalidTypeException | ClassNotLoadedException | InvocationException + | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + return allObjData; + } + + private void getAllObjectData(VirtualMachine vm, ThreadReference thread, Value methodExecution, Value tp) { + try { + resetData(); + + // this��ID��Type���擾���ĕ\�� + getRootThisState(vm, thread, (ObjectReference)methodExecution); + + // this�̎��ƒt�B�[���h��ID��Type��\�� (�Ăяo����ōċA) + getFieldsState(vm, thread, rootThisObjData, tp, ""); + + // ������ID��Type �y�т��̈��������ƒt�B�[���h��ID��Type��\�� (�Ăяo����ōċA) + getArgsState(vm, thread, methodExecution, tp, ""); + + allObjData.add(rootThisObjData); + for (VariableData argData : argsData) { + allObjData.add(argData); + } + } catch (InvalidTypeException | ClassNotLoadedException + | InvocationException | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + printAllObjData(); // �m�F�p + } + + private void getRootThisState(VirtualMachine vm, ThreadReference thread, ObjectReference methodExecution) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, methodExecution); + String thisObjId = ((StringReference)mc.callInstanceMethod("getThisObjId")).value(); + String thisClassName = ((StringReference)mc.callInstanceMethod("getThisClassName")).value(); + rootThisObjData = new VariableData("this", thisClassName, thisObjId); + } + + private void getFieldsState(VirtualMachine vm, ThreadReference thread, VariableData thisObjData, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + // �t�B�[���h��ID��Type���擾���ĕ\�� + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + ObjectReference trace = (ObjectReference)mc.callStaticMethod(TRACER, "TraceJSON", "getInstance"); + JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); + String declaringClassName = thisObjData.getClassName(); + IType type = javaEditorOperator.findIType(new JDIInstanceMethodCaller(vm, thread, null), declaringClassName); + try { + for (IField field : type.getFields()) { + if (Flags.isStatic(field.getFlags())) continue; + String fieldName = field.getDeclaringType().getElementName() + "." + field.getElementName(); // ���S����N���X�� + + // ���̃t�B�[���h�ɂ‚��Ă̍ŐV�̍X�V�����擾(FieldUpdate) + mc.changeReceiver(trace); + ObjectReference fieldUpdate = (ObjectReference)mc.callInstanceMethod("getRecentlyFieldUpdate", vm.mirrorOf(thisObjData.getId()), vm.mirrorOf(fieldName), tp); + if (fieldUpdate == null) continue; + + // �t�B�[���h��ID��Type���擾(String) + mc.changeReceiver(fieldUpdate); + String fieldObjId = ((StringReference)mc.callInstanceMethod("getValueObjId")).value(); + String fieldType = ((StringReference)mc.callInstanceMethod("getValueClassName")).value(); + VariableData fieldData = new VariableData(fieldName, fieldType, fieldObjId); + thisObjData.addChild(fieldData); + + // �擾�����t�B�[���h���I�u�W�F�N�g��z��̏ꍇ�ɁA���̃I�u�W�F�N�g��z�񂪎��ƒt�B�[���h�ɂ‚��Ă̏������s�� + switch (checkDeepHierarchy(fieldData)) { + case NONE: break; + case FIELD: getFieldsState(vm, thread, fieldData, tp, (indent + " ")); break; + case ARRAY: getArrayState(vm, thread, fieldData, tp, (indent + " ")); break; + } + } + } catch (JavaModelException e) { + e.printStackTrace(); + } + } + + /** + * ���̃t�B�[���h���Q�ƌ^�I�u�W�F�N�g���z�񂩂𔻒肵�Ĕ��茋�ʂ�Ԃ�.
+ * (�ϐ��r���[�ɕ\��������f�[�^���ċA�I�ɋ��߂邽�߂�, �Ăяo�����Ŏ��ɂǂ̃��\�b�h���ĂԂ��𔻒f����̂ɗ��p) + * + * @param objData + * @return FIELD: �Q�ƌ^�I�u�W�F�N�g�̏ꍇ
ARRAY: �z��̏ꍇ
NONE: ����ȊO�̏ꍇ + */ + private DeepHierarchy checkDeepHierarchy(VariableData objData) { + // �t�B�[���h��ID��Type���Ȃ��ꍇ��AType(=ActualType)��"---"�̏ꍇ�͉������Ȃ� + if (objData.getId() == null || objData.getId().isEmpty() + || objData.getClassName() == null || objData.getClassName().isEmpty()) { + return DeepHierarchy.NONE; + } + final String NULL_ACTUAL_TYPE = "---"; // �t�B�[���h�ɑ΂��Ė����I��null����ꂽ�ꍇ��ActualType�̎擾������ + if (objData.getClassName().equals(NULL_ACTUAL_TYPE)) return DeepHierarchy.NONE; + + final String ARRAY_SIGNATURE_HEAD = "["; // �z��̃V�O�l�`���̐擪�́A�z��̎��������� [ ���A�Ȃ� + if (objData.getClassName().startsWith(ARRAY_SIGNATURE_HEAD)) { + return DeepHierarchy.ARRAY; // �t�B�[���h��Type���z��^( [ �Ŏn�܂�)�ꍇ + } else { + String[] primitives = {"byte", "short", "int", "long", "float", "double", "char", "boolean"}; + if (!Arrays.asList(primitives).contains(objData.getClassName())) { + return DeepHierarchy.FIELD; // �t�B�[���h��Type���Q�ƌ^(=�I�u�W�F�N�g)�̏ꍇ + } + } + return DeepHierarchy.NONE; + } + + private void getArrayState(VirtualMachine vm, ThreadReference thread, VariableData arrayData, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + ObjectReference trace = (ObjectReference)mc.callStaticMethod(TRACER, "TraceJSON", "getInstance"); + for (int i = 0;; i++){ + // ���̔z��v�f�ɂ‚��Ă̍ŐV�̍X�V�����擾(ArrayUpdate) + IntegerValue index = vm.mirrorOf(i); + mc.changeReceiver(trace); + ObjectReference arrayUpdate = (ObjectReference)mc.callInstanceMethod("getRecentlyArrayUpdate", vm.mirrorOf(arrayData.getId()), index, tp); + if (arrayUpdate == null) { + // �z��̃T�C�Y���擾�ł��Ȃ����߁A�C���f�b�N�X���T�C�Y���߂̂Ƃ��Ɋm���ɔ���������@�Ƃ��ĉ����� + // �������A�z��v�f�̓r���ɖ���`���������ꍇ�ł��A�����Ă��܂��̂����_ + break; + } + String arrayIndexName = arrayData.getVariableName() + "[" + index.value() + "]"; + + // �z��v�f��ID��Type���擾(String) + mc.changeReceiver(arrayUpdate); + String valueObjId = ((StringReference)mc.callInstanceMethod("getValueObjectId")).value(); + String valueType = ((StringReference)mc.callInstanceMethod("getValueClassName")).value(); + VariableData arrayIndexData = new VariableData(arrayIndexName, valueType, valueObjId); + arrayData.addChild(arrayIndexData); + + // �擾�����z��v�f���I�u�W�F�N�g��z��̏ꍇ�ɁA���̃I�u�W�F�N�g��z�񂪎��ƒt�B�[���h�ɂ‚��Ă̏������s�� + switch (checkDeepHierarchy(arrayIndexData)) { + case NONE: break; + case FIELD: getFieldsState(vm, thread, arrayIndexData, tp, (indent + " ")); break; + case ARRAY: getArrayState(vm, thread, arrayIndexData, tp, (indent + " ")); break; + } + } + } + + private void getArgsState(VirtualMachine vm, ThreadReference thread, Value methodExecution, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + // methodExecution������arguments���擾(ArrayList)���A����arguments�̃T�C�Y���擾(int) + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution); + ObjectReference args = (ObjectReference)mc.callInstanceMethod("getArguments"); + final int ARGUMENTS_NUM = ((IntegerValue)mc.changeReceiver(args).callInstanceMethod("size")).value(); + if (ARGUMENTS_NUM > 0) { + JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); + IType type = javaEditorOperator.findIType(new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution)); + mc.changeReceiver((ObjectReference)methodExecution); + String methodSignature = ((StringReference)mc.callInstanceMethod("getSignature")).value(); + IMethod method = javaEditorOperator.findIMethod(type, methodSignature); + String[] argNames = getParameterNames(method); // ������IMethod���牼���������擾���� + for (int i = 0; i < ARGUMENTS_NUM; i++) { + String argName = (argNames.length == ARGUMENTS_NUM) ? argNames[i] : "arg" + i; // ���Ȃ��Ƃ������̌����s��v�̂Ƃ��͐����������������Ă��Ȃ� + mc.changeReceiver(args); + ObjectReference arg = (ObjectReference)mc.callInstanceMethod("get", vm.mirrorOf(i)); + mc.changeReceiver(arg); + String argId = ((StringReference)mc.callInstanceMethod("getId")).value(); + String argType = ((StringReference)mc.callInstanceMethod("getActualType")).value(); + VariableData argData = new VariableData(argName, argType, argId); + argsData.add(argData); + switch (checkDeepHierarchy(argData)) { + case NONE: break; + case FIELD: getFieldsState(vm, thread, argData, tp, (indent + " ")); break; + case ARRAY: getArrayState(vm, thread, argData, tp, (indent + " ")); break; + } + } + } + } + + private String[] getParameterNames(IMethod method) { + String[] argNames = new String[0]; + if (method != null) { + try { + argNames = method.getParameterNames(); + } catch (JavaModelException e) { + e.printStackTrace(); + } + } + return argNames; + } + + public void resetData() { + rootThisObjData = null; + argsData.clear(); + allObjData.clear(); + } + + private void printAllObjData() { + System.out.println(); + System.out.println("this"); + printObjData(allObjData.get(0), ""); + System.out.println(); + System.out.println("args"); + for (int i = 1; i < allObjData.size(); i++) { + printObjData(allObjData.get(i), ""); + } + System.out.println(); + } + + private void printObjData(VariableData data, String indent) { + StringBuilder sb = new StringBuilder(); + sb.append(data.getVariableName() + ": "); + sb.append(data.getClassName()); + sb.append("(" + "id = " + data.getId() + ")"); + System.out.println(indent + sb); + for (VariableData child : data.getChildren()) { + printObjData(child, indent + " "); + } + } + + private enum DeepHierarchy { + NONE, FIELD, ARRAY; + } +} + +class VariableData { + private String variableName; + private String className; + private String id; + private VariableData parent; + private List children = new ArrayList<>(); + + VariableData(String variableName, String className, String id) { + this.variableName = variableName; + this.className = className; + this.id = id; + } + + String getVariableName() { + return variableName; + } + + String getClassName() { + return className; + } + + String getId() { + return id; + } + + VariableData getParent() { + return parent; + } + + List getChildren() { + return children; + } + + void addChild(VariableData child) { + children.add(child); + child.parent = this; + } + + @Override + public String toString() { + return variableName + ": " + className + "(" + "id = " + id + ")"; + } +} \ No newline at end of file diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/Alias.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/Alias.java index 22ef1ca..f689679 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/Alias.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/Alias.java @@ -77,7 +77,13 @@ public String getMethodExecutionClassName() { MethodExecution methodExecution = occurrencePoint.getMethodExecution(); - return Trace.getDeclaringType(methodExecution.getSignature(), methodExecution.isConstructor()) + ".java"; + return Trace.getDeclaringType(methodExecution.getSignature(), methodExecution.isConstructor()); + } + + public String getSourceFileName() { + String methodExecutionClassName = getMethodExecutionClassName(); + methodExecutionClassName = methodExecutionClassName.replace(".", ""); + return methodExecutionClassName + ".java"; } public String getMethodSignature() { diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerAnalyzer.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerAnalyzer.java deleted file mode 100644 index db2350a..0000000 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerAnalyzer.java +++ /dev/null @@ -1,235 +0,0 @@ -package org.ntlab.reverseDebugger.analyzerProvider; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayAccess; -import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayCreate; -import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayUpdate; -import org.ntlab.traceAnalysisPlatform.tracer.trace.FieldAccess; -import org.ntlab.traceAnalysisPlatform.tracer.trace.FieldUpdate; -import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodExecution; -import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodInvocation; -import org.ntlab.traceAnalysisPlatform.tracer.trace.ObjectReference; -import org.ntlab.traceAnalysisPlatform.tracer.trace.Reference; -import org.ntlab.traceAnalysisPlatform.tracer.trace.Statement; -import org.ntlab.traceAnalysisPlatform.tracer.trace.Trace; -import org.ntlab.traceAnalysisPlatform.tracer.trace.TracePoint; - -public class ReverseDebuggerAnalyzer { - - public static ArrayList findAllSeedAliases(MethodExecution me) { - ArrayList seedAliasList = new ArrayList<>(); - List statements = me.getStatements(); - String[] primitives = {"byte", "short", "int", "long", "float", "double", "char", "boolean"}; - List primitiveList = Arrays.asList(primitives); - for (int i = 0; i < statements.size(); i++) { - TracePoint tp = me.getTracePoint(i); - Statement statement = statements.get(i); - if (statement instanceof FieldAccess) { - FieldAccess fa = (FieldAccess)statement; - String objId = fa.getContainerObjId(); - if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fa.getContainerClassName()))) { - seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_CONTAINER)); - } - objId = fa.getValueObjId(); - if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fa.getValueClassName()))) { - seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_FIELD)); - } - } else if (statement instanceof FieldUpdate) { - FieldUpdate fu = (FieldUpdate)statement; - String objId = fu.getContainerObjId(); - if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fu.getContainerClassName()))) { - seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_CONTAINER)); - } - objId = fu.getValueObjId(); - if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fu.getValueClassName()))) { - seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_FIELD)); - } - } else if (statement instanceof ArrayAccess) { - ArrayAccess aa = (ArrayAccess)statement; - String valueObjId = aa.getValueObjectId(); - if (valueObjId != null && !(valueObjId.equals("0")) && !(primitiveList.contains(aa.getValueClassName()))) { - seedAliasList.add(new Alias(valueObjId, tp, Alias.OCCURRENCE_EXP_ARRAY)); - } - } else if (statement instanceof ArrayUpdate) { - ArrayUpdate au = (ArrayUpdate)statement; - String valueObjId = au.getValueObjectId(); - if (valueObjId != null && !(valueObjId.equals("0")) && !(primitiveList.contains(au.getValueClassName()))) { - seedAliasList.add(new Alias(valueObjId, tp, Alias.OCCURRENCE_EXP_ARRAY)); - } - } else if (statement instanceof ArrayCreate) { - ArrayCreate ac = (ArrayCreate)statement; - String arrayObjId = ac.getArrayObjectId(); - if (arrayObjId != null && !(arrayObjId.equals("0")) && !(primitiveList.contains(ac.getArrayClassName()))) { - seedAliasList.add(new Alias(arrayObjId, tp, Alias.OCCURRENCE_EXP_RETURN)); - } - } else if (statement instanceof MethodInvocation) { - MethodExecution calledMe = ((MethodInvocation)statement).getCalledMethodExecution(); - String thisObjId = calledMe.getThisObjId(); - if (thisObjId != null && !(thisObjId.equals("0"))) { - seedAliasList.add(new Alias(thisObjId, tp, Alias.OCCURRENCE_EXP_RECEIVER)); - } - List args = calledMe.getArguments(); - for (int j = 0; j < args.size(); j++) { - ObjectReference arg = args.get(j); - String argValueId = arg.getId(); - if (argValueId != null && !(argValueId.equals("0")) && !(primitiveList.contains(arg.getActualType()))) { - seedAliasList.add(new Alias(argValueId, tp, (j + Alias.OCCURRENCE_EXP_FIRST_ARG))); - } - } - ObjectReference returnValue = calledMe.getReturnValue(); - if (returnValue != null) { - String returnValueId = returnValue.getId(); - if (returnValueId != null && !(returnValueId.equals("0") && !(primitiveList.contains(returnValue.getActualType())))) { - seedAliasList.add(new Alias(returnValueId, tp, Alias.OCCURRENCE_EXP_RETURN)); - } - } - } - } - return seedAliasList; - } - - private static TracePoint getRecentlyFieldUpdate(TracePoint tp) { - Statement statement = tp.getStatement(); - if (statement instanceof FieldAccess) { - FieldAccess fa = (FieldAccess)statement; - return Trace.getInstance().getFieldUpdateTracePoint(fa.getReference(), tp); - } - return null; - } - - private static TracePoint getRecentlyArrayUpdate(TracePoint tp) { - Statement statement = tp.getStatement(); - if (statement instanceof ArrayAccess) { - ArrayAccess aa = (ArrayAccess)statement; - // aa.getReference()���Ȃ��̂ʼn��ɂ�����ۂ�Reference������ēn�� - return Trace.getInstance().getArraySetTracePoint( - new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName()), - tp); - } - return null; - } - - public static ArrayList> getObjectFlow(Alias startAlias) { - ArrayList> aliasLists = new ArrayList<>(); - ArrayList aliasList = new ArrayList<>(); - aliasLists.add(aliasList); -// aliasList.add(alias); - String objId = startAlias.getObjectId(); - TracePoint tp = startAlias.getOccurrencePoint().duplicate(); - ArrayList> resultLists = getObjectFlow(aliasLists, objId, tp, 0); - return resultLists; - } - - private static ArrayList> getObjectFlow(ArrayList> aliasLists, - String objId, TracePoint tp, int side) { - ArrayList aliasList = aliasLists.get(aliasLists.size() - 1); // ����getObjectFlow���\�b�h���s���Ō��‚������G�C���A�X�����Ă������X�g - do { - Statement statement = tp.getStatement(); - if (statement instanceof FieldAccess) { - // �t�B�[���h�Q�Ƃ̏ꍇ - FieldAccess fa = (FieldAccess)statement; - if (fa.getValueObjId().equals(objId)) { - // ���Y�n�_�ł̃G�C���A�X�����X�g�ɒlj��������, �t�B�[���h�ŏI�X�V�ɔ�ԃp�^�[���Ƃ��̂܂ܑk��p�^�[���Ƃŕ��� - aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_FIELD)); - aliasList = new ArrayList<>(aliasList); // ���X�g���̂��f�B�[�v�R�s�[���Ă���(�t�B�[���h�ŏI�X�V�ɔ�ԍċA�����I�����, ���̂܂ܑk��p�^�[���ŗp����) - TracePoint fieldUpdateTp = getRecentlyFieldUpdate(tp); - aliasLists = getObjectFlow(aliasLists, objId, fieldUpdateTp, 0); - aliasLists.add(aliasList); // �ċA�����ɓ���O�Ƀf�B�[�v�R�s�[���Ă������X�g���Ō���ɒlj� (�ȍ~�̑k��ɂ���Č��‚����G�C���A�X�͂��̃��X�g�ɓ������) - } - } else if (statement instanceof ArrayAccess) { - // �z��v�f�Q�Ƃ̏ꍇ - ArrayAccess aa = (ArrayAccess)statement; - if (aa.getValueObjectId().equals(objId)) { - aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_ARRAY)); - aliasList = new ArrayList<>(aliasList); - TracePoint arrayUpdateTp = getRecentlyArrayUpdate(tp); - aliasLists = getObjectFlow(aliasLists, objId, arrayUpdateTp, 0); - aliasLists.add(aliasList); - } - } else if (statement instanceof FieldUpdate) { - // �t�B�[���h�X�V�̏ꍇ - FieldUpdate fu = (FieldUpdate)statement; - if (fu.getValueObjId().equals(objId)) { - aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_FIELD)); - } - } else if (statement instanceof ArrayUpdate) { - // �z��v�f�X�V�̏ꍇ - ArrayUpdate au = (ArrayUpdate)statement; - if (au.getValueObjectId().equals(objId)) { - aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_ARRAY)); - } - } else if (statement instanceof ArrayCreate) { - // �z�񐶐��̏ꍇ - ArrayCreate ac = (ArrayCreate)statement; - if (ac.getArrayObjectId().equals(objId)) { - aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_RETURN)); // �z�񐶐��� new �^��[] �̖߂�l - return aliasLists; // �z�񐶐��ӏ��̓G�C���A�X�̋N���Ȃ̂ł���ȑO�ɂ͂����Ȃ��͂� - } - } else if (statement instanceof MethodInvocation) { - // ���\�b�h�Ăяo���̏ꍇ - MethodExecution calledMethodExecution = ((MethodInvocation)statement).getCalledMethodExecution(); - ObjectReference returnValue = calledMethodExecution.getReturnValue(); - if (returnValue.getId().equals(objId)) { - // �߂�l�ɃG�C���A�X�̃I�u�W�F�N�gID����v�����ꍇ - ArrayList aliasListBeforeMethodBackEntry = new ArrayList<>(aliasList); // �Ăяo����̃��\�b�h���s�ɐ���O�̃G�C���A�X���X�g���R�s�[���Ă��� - aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_RETURN)); - if (calledMethodExecution.isConstructor()) { - return aliasLists; // �R���X�g���N�^�Ăяo���ӏ��̓G�C���A�X�̋N���Ȃ̂ł���ȑO�ɂ͂����Ȃ��͂� - } - TracePoint exitTp = calledMethodExecution.getExitPoint(); // �Ăяo�����\�b�h���s�̍ŏI�X�e�[�g�����g���w��tp���擾 - aliasLists = getObjectFlow(aliasLists, objId, exitTp, side + 1); // �Ăяo����̃��\�b�h���s�ɐ��� - aliasList = aliasLists.get(aliasLists.size() - 1); - if (aliasList.get(aliasList.size() - 1).isOrigin()) { - // �Ăяo����̃��\�b�h���s�ɐ�������ł��̃I�u�W�F�N�g�̋N��(�R���X�g���N�^or�z�񐶐�)�ɓ��B���Ă����ꍇ, �Ăяo����̃��\�b�h���s�ɐ���O�̃��X�g��p���ĐV�K�ɒǐՂ𑱍s���� - aliasLists.add(aliasListBeforeMethodBackEntry); - aliasList = aliasListBeforeMethodBackEntry; - } - } - } - } while (tp.stepBackOver()); // �Ăяo�����ɖ߂邩����ȏ�H��Ȃ��Ȃ�܂Ń��[�v - if (!tp.isValid()) { - return aliasLists; // ����ȏチ�\�b�h���s��k��Ȃ��ꍇ(main���\�b�h�̂���ɑO�Ȃ�)�͂��̎��_�ŏI�� - } - // --- ���̎��_�� tracePoint�� �Ăяo�������w���Ă��� (���O�܂ők���Ă������\�b�h���s�ɂ‚��Ẵ��\�b�h�Ăяo�����w���Ă���) --- - MethodExecution calledMethodExecution = ((MethodInvocation)tp.getStatement()).getCalledMethodExecution(); - ArrayList args = calledMethodExecution.getArguments(); - boolean isExistingInArgs = false; - for (int i = 0; i < args.size(); i++) { - if (args.get(i).getId().equals(objId)) { - // ���\�b�h�Ăяo���̎������ɃG�C���A�X�̃I�u�W�F�N�gID����v�����ꍇ - aliasList.add(new Alias(objId, tp.duplicate(), (i + Alias.OCCURRENCE_EXP_FIRST_ARG))); - isExistingInArgs = true; - if (side == 0) { - // �T���J�n���\�b�h���s�܂��̓t�B�[���h��z��v�f�̍ŏI�X�V�T���Ŕ�񂾐�̃��\�b�h���s����, �X�^�b�N�g���[�X�ł��ǂ��S���\�b�h���s�̏ꍇ - TracePoint previousTp = tp.duplicate(); - previousTp.stepBackOver(); - aliasLists = getObjectFlow(aliasLists, objId, previousTp, 0); // �Ăяo�����̃��\�b�h���s�ɖ߂� - } - } - } - if (!isExistingInArgs) { - aliasLists.remove(aliasLists.size() - 1); // �����ɃG�C���A�X���Ȃ������ꍇ�͂��̉�̒ǐՃG�C���A�X���X�g���폜���� - } - return aliasLists; - } - - public static int countMethodExecutionInTraceCollector(List methodExecutions, String targetSignature, int count, String indent) { - if (methodExecutions == null || methodExecutions.isEmpty()) { - return count; - } - for (int i = 0; i < methodExecutions.size(); i++) { - MethodExecution me = methodExecutions.get(i); - String signature = me.getSignature(); -// System.out.println(indent + signature); - if (targetSignature.equals(signature)) { - count++; - } - List children = me.getChildren(); - count = countMethodExecutionInTraceCollector(children, targetSignature, count, indent + "--------"); - } - return count; - } -} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerLaunchConfiguration.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerLaunchConfiguration.java index fa73e62..885141f 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerLaunchConfiguration.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerLaunchConfiguration.java @@ -8,9 +8,9 @@ import org.ntlab.traceAnalysisPlatform.IAdditionalLaunchConfiguration; public class ReverseDebuggerLaunchConfiguration implements IAdditionalLaunchConfiguration { - public static final String ANALYZER_PATH = "org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggerAnalyzer.class"; + public static final String ANALYZER_PATH = "org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggingAnalyzer.class"; public static final String ANALYZER_PACKAGE = "org.ntlab.reverseDebugger.analyzerProvider"; - public static final String ANALYZER_CLASS = "ReverseDebuggerAnalyzer"; + public static final String ANALYZER_CLASS = "ReverseDebuggingAnalyzer"; @Override public String[] getAdditionalClasspaths() { diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggingAnalyzer.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggingAnalyzer.java new file mode 100644 index 0000000..1d037c2 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggingAnalyzer.java @@ -0,0 +1,242 @@ +package org.ntlab.reverseDebugger.analyzerProvider; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayAccess; +import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayCreate; +import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayUpdate; +import org.ntlab.traceAnalysisPlatform.tracer.trace.FieldAccess; +import org.ntlab.traceAnalysisPlatform.tracer.trace.FieldUpdate; +import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodExecution; +import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodInvocation; +import org.ntlab.traceAnalysisPlatform.tracer.trace.ObjectReference; +import org.ntlab.traceAnalysisPlatform.tracer.trace.Reference; +import org.ntlab.traceAnalysisPlatform.tracer.trace.Statement; +import org.ntlab.traceAnalysisPlatform.tracer.trace.Trace; +import org.ntlab.traceAnalysisPlatform.tracer.trace.TraceJSON; +import org.ntlab.traceAnalysisPlatform.tracer.trace.TracePoint; + +public class ReverseDebuggingAnalyzer { + private static ReverseDebuggingAnalyzer getInstance = null; + private Trace trace; + + public ReverseDebuggingAnalyzer(Trace trace) { + this.trace = trace; + } + + private static ReverseDebuggingAnalyzer getInstance() { + if (getInstance == null) { + getInstance = new ReverseDebuggingAnalyzer(TraceJSON.getInstance()); + } + return getInstance; + } + + public Trace getTrace() { + return trace; + } + + public static ArrayList findAllSeedAliasesStatic(MethodExecution me) { + return getInstance().findAllSeedAliases(me); + } + + public ArrayList findAllSeedAliases(MethodExecution me) { + ArrayList seedAliasList = new ArrayList<>(); + List statements = me.getStatements(); + String[] primitives = {"byte", "short", "int", "long", "float", "double", "char", "boolean"}; + List primitiveList = Arrays.asList(primitives); + for (int i = 0; i < statements.size(); i++) { + TracePoint tp = me.getTracePoint(i); + Statement statement = statements.get(i); + if (statement instanceof FieldAccess) { + FieldAccess fa = (FieldAccess)statement; + String objId = fa.getContainerObjId(); + if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fa.getContainerClassName()))) { + seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_CONTAINER)); + } + objId = fa.getValueObjId(); + if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fa.getValueClassName()))) { + seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_FIELD)); + } + } else if (statement instanceof FieldUpdate) { + FieldUpdate fu = (FieldUpdate)statement; + String objId = fu.getContainerObjId(); + if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fu.getContainerClassName()))) { + seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_CONTAINER)); + } + objId = fu.getValueObjId(); + if (objId != null && !(objId.equals("0")) && !(primitiveList.contains(fu.getValueClassName()))) { + seedAliasList.add(new Alias(objId, tp, Alias.OCCURRENCE_EXP_FIELD)); + } + } else if (statement instanceof ArrayAccess) { + ArrayAccess aa = (ArrayAccess)statement; + String valueObjId = aa.getValueObjectId(); + if (valueObjId != null && !(valueObjId.equals("0")) && !(primitiveList.contains(aa.getValueClassName()))) { + seedAliasList.add(new Alias(valueObjId, tp, Alias.OCCURRENCE_EXP_ARRAY)); + } + } else if (statement instanceof ArrayUpdate) { + ArrayUpdate au = (ArrayUpdate)statement; + String valueObjId = au.getValueObjectId(); + if (valueObjId != null && !(valueObjId.equals("0")) && !(primitiveList.contains(au.getValueClassName()))) { + seedAliasList.add(new Alias(valueObjId, tp, Alias.OCCURRENCE_EXP_ARRAY)); + } + } else if (statement instanceof ArrayCreate) { + ArrayCreate ac = (ArrayCreate)statement; + String arrayObjId = ac.getArrayObjectId(); + if (arrayObjId != null && !(arrayObjId.equals("0")) && !(primitiveList.contains(ac.getArrayClassName()))) { + seedAliasList.add(new Alias(arrayObjId, tp, Alias.OCCURRENCE_EXP_RETURN)); + } + } else if (statement instanceof MethodInvocation) { + MethodExecution calledMe = ((MethodInvocation)statement).getCalledMethodExecution(); + String thisObjId = calledMe.getThisObjId(); + if (thisObjId != null && !(thisObjId.equals("0"))) { + seedAliasList.add(new Alias(thisObjId, tp, Alias.OCCURRENCE_EXP_RECEIVER)); + } + List args = calledMe.getArguments(); + for (int j = 0; j < args.size(); j++) { + ObjectReference arg = args.get(j); + String argValueId = arg.getId(); + if (argValueId != null && !(argValueId.equals("0")) && !(primitiveList.contains(arg.getActualType()))) { + seedAliasList.add(new Alias(argValueId, tp, (j + Alias.OCCURRENCE_EXP_FIRST_ARG))); + } + } + ObjectReference returnValue = calledMe.getReturnValue(); + if (returnValue != null) { + String returnValueId = returnValue.getId(); + if (returnValueId != null && !(returnValueId.equals("0") && !(primitiveList.contains(returnValue.getActualType())))) { + seedAliasList.add(new Alias(returnValueId, tp, Alias.OCCURRENCE_EXP_RETURN)); + } + } + } + } + return seedAliasList; + } + + private TracePoint getRecentlyFieldUpdate(TracePoint tp) { + Statement statement = tp.getStatement(); + if (statement instanceof FieldAccess) { + FieldAccess fa = (FieldAccess)statement; + return trace.getFieldUpdateTracePoint(fa.getReference(), tp); + } + return null; + } + + private TracePoint getRecentlyArrayUpdate(TracePoint tp) { + Statement statement = tp.getStatement(); + if (statement instanceof ArrayAccess) { + ArrayAccess aa = (ArrayAccess)statement; + // aa.getReference()���Ȃ��̂ʼn��ɂ�����ۂ�Reference������ēn�� + return trace.getArraySetTracePoint(new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName()), tp); + } + return null; + } + + public static ArrayList> getObjectFlowStatic(Alias startAlias) { + return getInstance().getObjectFlow(startAlias); + } + + public ArrayList> getObjectFlow(Alias startAlias) { + ArrayList> aliasLists = new ArrayList<>(); + ArrayList aliasList = new ArrayList<>(); + aliasLists.add(aliasList); +// aliasList.add(alias); + String objId = startAlias.getObjectId(); + TracePoint tp = startAlias.getOccurrencePoint().duplicate(); + ArrayList> resultLists = getObjectFlow(aliasLists, objId, tp, 0); + return resultLists; + } + + private ArrayList> getObjectFlow(ArrayList> aliasLists, + String objId, TracePoint tp, int side) { + ArrayList aliasList = aliasLists.get(aliasLists.size() - 1); // ����getObjectFlow���\�b�h���s���Ō��‚������G�C���A�X�����Ă������X�g + do { + Statement statement = tp.getStatement(); + if (statement instanceof FieldAccess) { + // �t�B�[���h�Q�Ƃ̏ꍇ + FieldAccess fa = (FieldAccess)statement; + if (fa.getValueObjId().equals(objId)) { + // ���Y�n�_�ł̃G�C���A�X�����X�g�ɒlj��������, �t�B�[���h�ŏI�X�V�ɔ�ԃp�^�[���Ƃ��̂܂ܑk��p�^�[���Ƃŕ��� + aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_FIELD)); + aliasList = new ArrayList<>(aliasList); // ���X�g���̂��f�B�[�v�R�s�[���Ă���(�t�B�[���h�ŏI�X�V�ɔ�ԍċA�����I�����, ���̂܂ܑk��p�^�[���ŗp����) + TracePoint fieldUpdateTp = getRecentlyFieldUpdate(tp); + aliasLists = getObjectFlow(aliasLists, objId, fieldUpdateTp, 0); + aliasLists.add(aliasList); // �ċA�����ɓ���O�Ƀf�B�[�v�R�s�[���Ă������X�g���Ō���ɒlj� (�ȍ~�̑k��ɂ���Č��‚����G�C���A�X�͂��̃��X�g�ɓ������) + } + } else if (statement instanceof ArrayAccess) { + // �z��v�f�Q�Ƃ̏ꍇ + ArrayAccess aa = (ArrayAccess)statement; + if (aa.getValueObjectId().equals(objId)) { + aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_ARRAY)); + aliasList = new ArrayList<>(aliasList); + TracePoint arrayUpdateTp = getRecentlyArrayUpdate(tp); + aliasLists = getObjectFlow(aliasLists, objId, arrayUpdateTp, 0); + aliasLists.add(aliasList); + } + } else if (statement instanceof FieldUpdate) { + // �t�B�[���h�X�V�̏ꍇ + FieldUpdate fu = (FieldUpdate)statement; + if (fu.getValueObjId().equals(objId)) { + aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_FIELD)); + } + } else if (statement instanceof ArrayUpdate) { + // �z��v�f�X�V�̏ꍇ + ArrayUpdate au = (ArrayUpdate)statement; + if (au.getValueObjectId().equals(objId)) { + aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_ARRAY)); + } + } else if (statement instanceof ArrayCreate) { + // �z�񐶐��̏ꍇ + ArrayCreate ac = (ArrayCreate)statement; + if (ac.getArrayObjectId().equals(objId)) { + aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_RETURN)); // �z�񐶐��� new �^��[] �̖߂�l + return aliasLists; // �z�񐶐��ӏ��̓G�C���A�X�̋N���Ȃ̂ł���ȑO�ɂ͂����Ȃ��͂� + } + } else if (statement instanceof MethodInvocation) { + // ���\�b�h�Ăяo���̏ꍇ + MethodExecution calledMethodExecution = ((MethodInvocation)statement).getCalledMethodExecution(); + ObjectReference returnValue = calledMethodExecution.getReturnValue(); + if (returnValue.getId().equals(objId)) { + // �߂�l�ɃG�C���A�X�̃I�u�W�F�N�gID����v�����ꍇ + ArrayList aliasListBeforeMethodBackEntry = new ArrayList<>(aliasList); // �Ăяo����̃��\�b�h���s�ɐ���O�̃G�C���A�X���X�g���R�s�[���Ă��� + aliasList.add(new Alias(objId, tp.duplicate(), Alias.OCCURRENCE_EXP_RETURN)); + if (calledMethodExecution.isConstructor()) { + return aliasLists; // �R���X�g���N�^�Ăяo���ӏ��̓G�C���A�X�̋N���Ȃ̂ł���ȑO�ɂ͂����Ȃ��͂� + } + TracePoint exitTp = calledMethodExecution.getExitPoint(); // �Ăяo�����\�b�h���s�̍ŏI�X�e�[�g�����g���w��tp���擾 + aliasLists = getObjectFlow(aliasLists, objId, exitTp, side + 1); // �Ăяo����̃��\�b�h���s�ɐ��� + aliasList = aliasLists.get(aliasLists.size() - 1); + if (aliasList.get(aliasList.size() - 1).isOrigin()) { + // �Ăяo����̃��\�b�h���s�ɐ�������ł��̃I�u�W�F�N�g�̋N��(�R���X�g���N�^or�z�񐶐�)�ɓ��B���Ă����ꍇ, �Ăяo����̃��\�b�h���s�ɐ���O�̃��X�g��p���ĐV�K�ɒǐՂ𑱍s���� + aliasLists.add(aliasListBeforeMethodBackEntry); + aliasList = aliasListBeforeMethodBackEntry; + } + } + } + } while (tp.stepBackOver()); // �Ăяo�����ɖ߂邩����ȏ�H��Ȃ��Ȃ�܂Ń��[�v + if (!tp.isValid()) { + return aliasLists; // ����ȏチ�\�b�h���s��k��Ȃ��ꍇ(main���\�b�h�̂���ɑO�Ȃ�)�͂��̎��_�ŏI�� + } + // --- ���̎��_�� tracePoint�� �Ăяo�������w���Ă��� (���O�܂ők���Ă������\�b�h���s�ɂ‚��Ẵ��\�b�h�Ăяo�����w���Ă���) --- + MethodExecution calledMethodExecution = ((MethodInvocation)tp.getStatement()).getCalledMethodExecution(); + ArrayList args = calledMethodExecution.getArguments(); + boolean isExistingInArgs = false; + for (int i = 0; i < args.size(); i++) { + if (args.get(i).getId().equals(objId)) { + // ���\�b�h�Ăяo���̎������ɃG�C���A�X�̃I�u�W�F�N�gID����v�����ꍇ + aliasList.add(new Alias(objId, tp.duplicate(), (i + Alias.OCCURRENCE_EXP_FIRST_ARG))); + isExistingInArgs = true; + if (side == 0) { + // �T���J�n���\�b�h���s�܂��̓t�B�[���h��z��v�f�̍ŏI�X�V�T���Ŕ�񂾐�̃��\�b�h���s����, �X�^�b�N�g���[�X�ł��ǂ��S���\�b�h���s�̏ꍇ + TracePoint previousTp = tp.duplicate(); + previousTp.stepBackOver(); + aliasLists = getObjectFlow(aliasLists, objId, previousTp, 0); // �Ăяo�����̃��\�b�h���s�ɖ߂� + } + } + } + if (!isExistingInArgs) { + aliasLists.remove(aliasLists.size() - 1); // �����ɃG�C���A�X���Ȃ������ꍇ�͂��̉�̒ǐՃG�C���A�X���X�g���폜���� + } + return aliasLists; + } +}