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..b3d7708 100644 --- a/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF +++ b/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ 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, 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/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/SeedAliases.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java index e88f45a..a775d34 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliases.java @@ -122,7 +122,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/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/ReverseDebuggingAnalyzer.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggingAnalyzer.java new file mode 100644 index 0000000..30c914e --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/analyzerProvider/ReverseDebuggingAnalyzer.java @@ -0,0 +1,244 @@ +package org.ntlab.reverseDebugger.analyzerProvider; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.ntlab.reverseDebugger.analyzerProvider.Alias; +import org.ntlab.reverseDebugger.analyzerProvider.ReverseDebuggingAnalyzer; +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; + } +}