From 9c3084ccee6af48629bf238b9ec919cb47c69296 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Wed, 22 Sep 2021 22:05:28 +0000 Subject: [PATCH] GP-1288: more visible clues --- .../agent/dbgeng/dbgeng/DebugControl.java | 14 +++ .../agent/dbgeng/manager/DbgEventFilter.java | 2 + .../dbgeng/manager/DbgEventsListener.java | 9 ++ .../manager/DbgEventsListenerAdapter.java | 6 ++ .../cmd/DbgListEventFiltersCommand.java | 5 +- .../cmd/DbgListExceptionFiltersCommand.java | 2 +- .../cmd/DbgToggleContinuationCommand.java | 60 ++++++++++++ .../cmd/DbgToggleExecutionCommand.java | 60 ++++++++++++ .../manager/impl/DbgEventFilterImpl.java | 11 ++- .../manager/impl/DbgExceptionFilterImpl.java | 5 +- .../dbgeng/manager/impl/DbgManagerImpl.java | 9 +- .../agent/dbgeng/model/AbstractDbgModel.java | 2 + .../model/iface2/DbgModelTargetEvent.java | 17 ++-- .../iface2/DbgModelTargetEventOption.java | 5 - .../model/iface2/DbgModelTargetException.java | 7 +- .../agent/dbgeng/model/impl/DbgModelImpl.java | 1 + ...DbgModelTargetContinuationOptionImpl.java} | 69 ++++++-------- .../model/impl/DbgModelTargetEventImpl.java | 51 +++++++++- .../impl/DbgModelTargetExceptionImpl.java | 31 ++++++- .../DbgModelTargetExecutionOptionImpl.java | 81 ++++++++++++++++ .../dbgmodel/model/impl/DbgModel2Impl.java | 5 + .../core/debug/gui/DebuggerResources.java | 16 ++++ .../gui/objects/DebuggerObjectsProvider.java | 92 +++++++++++-------- 23 files changed, 454 insertions(+), 106 deletions(-) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java rename Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/{DbgModelTargetEventOptionImpl.java => DbgModelTargetContinuationOptionImpl.java} (52%) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java index bcf66bdfa9..46dfa561f1 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java @@ -114,6 +114,20 @@ public interface DebugControl extends DebugControlReentrant { ; } + public static enum DebugFilterOrdinals { + DEBUG_FILTER_CREATE_THREAD, // + DEBUG_FILTER_EXIT_THREAD, // + DEBUG_FILTER_CREATE_PROCESS, // + DEBUG_FILTER_EXIT_PROCESS, // + DEBUG_FILTER_LOAD_MODULE, // + DEBUG_FILTER_UNLOAD_MODULE, // + DEBUG_FILTER_SYSTEM_ERROR, // + DEBUG_FILTER_INITIAL_BREAKPOINT, // + DEBUG_FILTER_INITIAL_MODULE_LOAD, // + DEBUG_FILTER_DEBUGGEE_OUTPUT, // + ; + } + public static enum DebugFilterExecutionOption { DEBUG_FILTER_BREAK(0, "Break"), // DEBUG_FILTER_SECOND_CHANCE_BREAK(1, "Second-chance Break"), // diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java index cf7946a74b..e5052cc383 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java @@ -17,6 +17,8 @@ package agent.dbgeng.manager; public interface DbgEventFilter { + int getIndex(); + String getName(); String getCmd(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java index de3d2595c5..768fa6361b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java @@ -17,6 +17,7 @@ package agent.dbgeng.manager; import agent.dbgeng.dbgeng.*; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; +import agent.dbgeng.manager.evt.AbstractDbgEvent; public interface DbgEventsListener { @@ -123,6 +124,14 @@ public interface DbgEventsListener { */ void threadSelected(DbgThread thread, DbgStackFrame frame, DbgCause cause); + /** + * A system event has occurred (gained focus) + * + * @param event a handle to the current event + * @param cause the cause of this event + */ + void eventSelected(AbstractDbgEvent event, DbgCause cause); + /** * A module has been loaded by an process * diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java index 80781c35db..794e667600 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java @@ -17,6 +17,7 @@ package agent.dbgeng.manager; import agent.dbgeng.dbgeng.*; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; +import agent.dbgeng.manager.evt.AbstractDbgEvent; public interface DbgEventsListenerAdapter extends DbgEventsListener { @@ -82,6 +83,11 @@ public interface DbgEventsListenerAdapter extends DbgEventsListener { // Extension point } + @Override + public default void eventSelected(AbstractDbgEvent event, DbgCause cause) { + // Extension point + } + @Override public default void moduleLoaded(DbgProcess process, DebugModuleInfo info, DbgCause cause) { // Extension point diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java index 8c2bf4cea3..c63254af28 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java @@ -48,8 +48,9 @@ public class DbgListEventFiltersCommand String text = control.getEventFilterText(i); String cmd = control.getEventFilterCommand(i); DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(i); - DbgEventFilterImpl f = new DbgEventFilterImpl(text, cmd, p.ExecutionOption.intValue(), - p.ContinueOption.intValue()); + DbgEventFilterImpl f = + new DbgEventFilterImpl(i, text, cmd, p.ExecutionOption.intValue(), + p.ContinueOption.intValue()); result.add(f); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java index 8006d2ecd1..27a19a04c6 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -52,7 +52,7 @@ public class DbgListExceptionFiltersCommand String text = control.getEventFilterText(nEvents + i); String cmd = control.getEventFilterCommand(nEvents + i); String cmd2 = control.getExceptionFilterSecondCommand(nEvents + i); - DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(text, cmd, cmd2, + DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(i, text, cmd, cmd2, p.ExecutionOption.intValue(), p.ContinueOption.intValue(), p.ExceptionCode.longValue()); result.add(filter); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java new file mode 100644 index 0000000000..743996685f --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java @@ -0,0 +1,60 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.dbgeng.manager.cmd; + +import com.sun.jna.platform.win32.WinDef.ULONG; + +import agent.dbgeng.dbgeng.*; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; +import agent.dbgeng.manager.impl.DbgManagerImpl; + +public class DbgToggleContinuationCommand + extends AbstractDbgCommand { + + private int index; + private DebugFilterContinuationOption optionCont; + + public DbgToggleContinuationCommand(DbgManagerImpl manager, int index, + DebugFilterContinuationOption optionCont) { + super(manager); + this.index = index; + this.optionCont = optionCont; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + DebugFilterInformation info = control.getNumberEventFilters(); + int nEvents = info.getNumberEvents(); + int nExcs = info.getNumberSpecificExceptions(); + if (index < nEvents) { + DebugSpecificFilterInformation exc = + control.getSpecificFilterParameters(0, nEvents); + DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(index); + p.ContinueOption = new ULONG(optionCont.ordinal()); + control.setSpecificFilterParameters(0, nEvents, exc); + } + else { + DebugExceptionFilterInformation exc = + control.getExceptionFilterParameters(nEvents, null, nExcs); + DEBUG_EXCEPTION_FILTER_PARAMETERS p = exc.getParameter(index); + p.ContinueOption = new ULONG(optionCont.ordinal()); + control.setExceptionFilterParameters(nExcs, exc); + } + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java new file mode 100644 index 0000000000..e612f1e1e8 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java @@ -0,0 +1,60 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.dbgeng.manager.cmd; + +import com.sun.jna.platform.win32.WinDef.ULONG; + +import agent.dbgeng.dbgeng.*; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; +import agent.dbgeng.manager.impl.DbgManagerImpl; + +public class DbgToggleExecutionCommand + extends AbstractDbgCommand { + + private int index; + private DebugFilterExecutionOption optionCont; + + public DbgToggleExecutionCommand(DbgManagerImpl manager, int index, + DebugFilterExecutionOption optionCont) { + super(manager); + this.index = index; + this.optionCont = optionCont; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + DebugFilterInformation info = control.getNumberEventFilters(); + int nEvents = info.getNumberEvents(); + int nExcs = info.getNumberSpecificExceptions(); + if (index < nEvents) { + DebugSpecificFilterInformation exc = + control.getSpecificFilterParameters(0, nEvents); + DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(index); + p.ExecutionOption = new ULONG(optionCont.ordinal()); + control.setSpecificFilterParameters(0, nEvents, exc); + } + else { + DebugExceptionFilterInformation exc = + control.getExceptionFilterParameters(nEvents, null, nExcs); + DEBUG_EXCEPTION_FILTER_PARAMETERS p = exc.getParameter(index); + p.ExecutionOption = new ULONG(optionCont.ordinal()); + control.setExceptionFilterParameters(nExcs, exc); + } + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java index 9fbff3fda0..9e277d0210 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java @@ -18,18 +18,27 @@ package agent.dbgeng.manager.impl; import agent.dbgeng.manager.DbgEventFilter; public class DbgEventFilterImpl implements DbgEventFilter { + + protected int index; protected final String text; protected final String cmd; protected int executionOption; protected int continueOption; - public DbgEventFilterImpl(String text, String cmd, int executionOption, int continueOption) { + public DbgEventFilterImpl(int index, String text, String cmd, int executionOption, + int continueOption) { + this.index = index; this.text = text; this.cmd = cmd; this.setExecutionOption(executionOption); this.setContinueOption(continueOption); } + @Override + public int getIndex() { + return index; + } + @Override public String getName() { return text; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java index 4e32f78cca..7f57150f91 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java @@ -22,9 +22,10 @@ public class DbgExceptionFilterImpl extends DbgEventFilterImpl implements DbgExc private final String cmd2; private long exceptionCode; - public DbgExceptionFilterImpl(String text, String cmd, String cmd2, int executionOption, + public DbgExceptionFilterImpl(int index, String text, String cmd, String cmd2, + int executionOption, int continueOption, long exceptionCode) { - super(text, cmd, executionOption, continueOption); + super(index, text, cmd, executionOption, continueOption); this.cmd2 = cmd2; this.exceptionCode = exceptionCode; } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java index 7cc617693d..e969b3b5a9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java @@ -685,6 +685,7 @@ public class DbgManagerImpl implements DbgManager { */ protected DebugStatus processException(DbgExceptionEvent evt, Void v) { DebugThreadId eventId = updateState(); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadSelected(eventThread, null, evt.getCause()); DebugExceptionRecord64 info = evt.getInfo(); @@ -710,6 +711,7 @@ public class DbgManagerImpl implements DbgManager { DbgProcessImpl process = getCurrentProcess(); int tid = so.getCurrentThreadSystemId(); DbgThreadImpl thread = getThreadComputeIfAbsent(eventId, process, tid); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadCreated(thread, DbgCause.Causes.UNCLAIMED); getEventListeners().fire.threadSelected(thread, null, evt.getCause()); @@ -735,6 +737,7 @@ public class DbgManagerImpl implements DbgManager { thread.remove(); } process.threadExited(eventId); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadExited(eventId, process, evt.getCause()); String key = Integer.toHexString(eventId.id); @@ -783,6 +786,7 @@ public class DbgManagerImpl implements DbgManager { //so.setCurrentProcessId(id); int pid = so.getCurrentProcessSystemId(); DbgProcessImpl proc = getProcessComputeIfAbsent(id, pid); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.processAdded(proc, evt.getCause()); getEventListeners().fire.processSelected(proc, evt.getCause()); @@ -815,8 +819,9 @@ public class DbgManagerImpl implements DbgManager { DbgThreadImpl thread = getCurrentThread(); DbgProcessImpl process = getCurrentProcess(); process.setExitCode(Long.valueOf(evt.getInfo())); - getEventListeners().fire.threadExited(eventId, process, evt.getCause()); + getEventListeners().fire.eventSelected(evt, evt.getCause()); + getEventListeners().fire.threadExited(eventId, process, evt.getCause()); getEventListeners().fire.processExited(process, evt.getCause()); for (DebugBreakpoint bpt : getBreakpoints()) { @@ -867,6 +872,7 @@ public class DbgManagerImpl implements DbgManager { DbgProcessImpl process = getCurrentProcess(); DebugModuleInfo info = evt.getInfo(); process.moduleLoaded(info); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.moduleLoaded(process, info, evt.getCause()); String key = info.getModuleName(); @@ -888,6 +894,7 @@ public class DbgManagerImpl implements DbgManager { DbgProcessImpl process = getCurrentProcess(); DebugModuleInfo info = evt.getInfo(); process.moduleUnloaded(info); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.moduleUnloaded(process, info, evt.getCause()); String key = info.getModuleName(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java index de1a51b3a3..a93feae241 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java @@ -42,4 +42,6 @@ public abstract class AbstractDbgModel extends AbstractDebuggerObjectModel { public abstract TargetObject getModelObject(Object object); + public abstract void deleteModelObject(Object object); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java index dfbcc6eb35..c03e282925 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java @@ -15,15 +15,18 @@ */ package agent.dbgeng.model.iface2; -import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.*; +import agent.dbgeng.manager.evt.AbstractDbgEvent; +import agent.dbgeng.model.iface1.DbgModelSelectableObject; -public interface DbgModelTargetEvent extends DbgModelTargetObject { - - @Override - public default String getDisplay() { - return getName(); - } +public interface DbgModelTargetEvent extends DbgModelSelectableObject, DbgEventsListenerAdapter // +{ public DbgEventFilter getFilter(); + public int getEventIndex(); + + @Override + void eventSelected(AbstractDbgEvent event, DbgCause cause); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java index 3300d54e76..2d2df7d5e0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java @@ -19,9 +19,4 @@ import ghidra.dbg.target.TargetTogglable; public interface DbgModelTargetEventOption extends DbgModelTargetObject, TargetTogglable { - @Override - public default String getDisplay() { - return getName(); - } - } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java index 34c48922f4..a28c5731d0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java @@ -17,12 +17,7 @@ package agent.dbgeng.model.iface2; import agent.dbgeng.manager.DbgExceptionFilter; -public interface DbgModelTargetException extends DbgModelTargetObject { - - @Override - public default String getDisplay() { - return getName(); - } +public interface DbgModelTargetException extends DbgModelTargetEvent { public DbgExceptionFilter getFilter(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java index b05703ca08..b030ff7c7e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java @@ -164,6 +164,7 @@ public class DbgModelImpl extends AbstractDbgModel implements DebuggerObjectMode return objectMap.get(object); } + @Override public void deleteModelObject(Object object) { objectMap.remove(object); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java similarity index 52% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java index 15a3d13011..4633bf7b39 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java @@ -20,75 +20,66 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; -import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.manager.cmd.DbgToggleContinuationCommand; +import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; -import ghidra.dbg.util.PathUtils; @TargetObjectSchemaInfo( - name = "Event", + name = "ContinuationFilter", elements = { @TargetElementType(type = Void.class) }, attributes = { @TargetAttributeType(type = Object.class) }) -public class DbgModelTargetEventOptionImpl extends DbgModelTargetObjectImpl +public class DbgModelTargetContinuationOptionImpl extends DbgModelTargetObjectImpl implements DbgModelTargetEventOption { - protected static String keyFilter(DebugFilterExecutionOption option) { - return PathUtils.makeKey(option.description); - } - - protected static String keyFilter(DebugFilterContinuationOption option) { - return PathUtils.makeKey(option.description); - } - - private DebugFilterExecutionOption optionEx; + private DbgModelTargetEvent event; private DebugFilterContinuationOption optionCont; - public DbgModelTargetEventOptionImpl(DbgModelTargetEvent event, - DebugFilterExecutionOption option) { - super(event.getModel(), event, keyFilter(option), "EventFilter"); + public DbgModelTargetContinuationOptionImpl(DbgModelTargetEvent event, + DebugFilterContinuationOption option) { + super(event.getModel(), event, "Continue", "ContinuationFilter"); this.getModel().addModelObject(option, this); - this.optionEx = option; + this.event = event; + this.optionCont = option; + setAttributes(); } - public DbgModelTargetEventOptionImpl(DbgModelTargetEvent event, + public DbgModelTargetContinuationOptionImpl(DbgModelTargetException exc, DebugFilterContinuationOption option) { - super(event.getModel(), event, keyFilter(option), "EventFilter"); - this.getModel().addModelObject(option, this); - this.optionCont = option; - } - - public DbgModelTargetEventOptionImpl(DbgModelTargetException exc, - DebugFilterExecutionOption option) { - super(exc.getModel(), exc, keyFilter(option), "EventFilter"); - this.getModel().addModelObject(option, this); - this.optionEx = option; - } - - public DbgModelTargetEventOptionImpl(DbgModelTargetException exc, - DebugFilterContinuationOption option) { - super(exc.getModel(), exc, keyFilter(option), "EventFilter"); + super(exc.getModel(), exc, "Continue", "ContinuationFilter"); + this.event = exc; this.getModel().addModelObject(option, this); this.optionCont = option; + setAttributes(); } @Override public CompletableFuture disable() { - // TODO Auto-generated method stub - return null; + DbgManagerImpl manager = getManager(); + optionCont = DebugFilterContinuationOption.DEBUG_FILTER_GO_NOT_HANDLED; + setAttributes(); + return manager.execute( + new DbgToggleContinuationCommand(manager, event.getEventIndex(), optionCont)); } @Override public CompletableFuture enable() { - // TODO Auto-generated method stub - return null; + DbgManagerImpl manager = getManager(); + optionCont = DebugFilterContinuationOption.DEBUG_FILTER_GO_HANDLED; + setAttributes(); + return manager.execute( + new DbgToggleContinuationCommand(manager, event.getEventIndex(), optionCont)); } public void setAttributes() { changeAttributes(List.of(), List.of(), Map.of( // - DISPLAY_ATTRIBUTE_NAME, getName() // - ), "Initialized"); + DISPLAY_ATTRIBUTE_NAME, getName() + " : " + optionCont.description, // + VALUE_ATTRIBUTE_NAME, optionCont, // + ENABLED_ATTRIBUTE_NAME, + optionCont.equals(DebugFilterContinuationOption.DEBUG_FILTER_GO_HANDLED)), + "Refreshed"); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 3b5e644c8b..62b9aa7fde 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -18,9 +18,10 @@ package agent.dbgeng.model.impl; import java.util.List; import java.util.Map; -import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; -import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.dbgeng.DebugControl.*; +import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.evt.*; import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -55,8 +56,8 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl DebugFilterExecutionOption.getByNumber(filter.getExecutionOption()); DebugFilterContinuationOption cont = DebugFilterContinuationOption.getByNumber(filter.getContinueOption()); - execOption = new DbgModelTargetEventOptionImpl(this, exec); - contOption = new DbgModelTargetEventOptionImpl(this, cont); + execOption = new DbgModelTargetExecutionOptionImpl(this, exec); + contOption = new DbgModelTargetContinuationOptionImpl(this, cont); changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // @@ -64,6 +65,8 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl "Execute", execOption, // "Continue", contOption // ), "Initialized"); + + getManager().addEventsListener(this); } @Override @@ -71,4 +74,44 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl return filter; } + @Override + public int getEventIndex() { + return filter.getIndex(); + } + + @Override + public void eventSelected(AbstractDbgEvent event, DbgCause cause) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, false), "Refreshed"); + if (event instanceof DbgThreadCreatedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_CREATE_THREAD.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgThreadExitedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_EXIT_THREAD.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgProcessCreatedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_CREATE_PROCESS.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgProcessExitedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_EXIT_PROCESS.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgModuleLoadedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_LOAD_MODULE.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgModuleUnloadedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_UNLOAD_MODULE.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index 2f58e36bac..3976a1809b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -20,8 +20,14 @@ import java.util.Map; import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.dbgeng.DebugExceptionRecord64; +import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.manager.evt.AbstractDbgEvent; +import agent.dbgeng.manager.evt.DbgExceptionEvent; +import agent.dbgeng.model.iface1.DbgModelTargetFocusScope; import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.TargetFocusScope; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -56,8 +62,8 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl DebugFilterExecutionOption.getByNumber(filter.getExecutionOption()); DebugFilterContinuationOption cont = DebugFilterContinuationOption.getByNumber(filter.getContinueOption()); - execOption = new DbgModelTargetEventOptionImpl(this, exec); - contOption = new DbgModelTargetEventOptionImpl(this, cont); + execOption = new DbgModelTargetExecutionOptionImpl(this, exec); + contOption = new DbgModelTargetContinuationOptionImpl(this, cont); changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // @@ -67,6 +73,8 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl "Continue", contOption, // "Exception", filter.getExceptionCode() // ), "Initialized"); + + getManager().addEventsListener(this); } @Override @@ -74,4 +82,23 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl return filter; } + @Override + public int getEventIndex() { + return filter.getIndex(); + } + + @Override + public void eventSelected(AbstractDbgEvent event, DbgCause cause) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, false), "Refreshed"); + if (event instanceof DbgExceptionEvent) { + DebugExceptionRecord64 info = (DebugExceptionRecord64) event.getInfo(); + if (info.code == Long.parseLong(filter.getExceptionCode(), 16)) { + ((DbgModelTargetFocusScope) searchForSuitable(TargetFocusScope.class)) + .setFocus(this); + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + } + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java new file mode 100644 index 0000000000..ffc81fa1d7 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java @@ -0,0 +1,81 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.dbgeng.model.impl; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.manager.cmd.DbgToggleExecutionCommand; +import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.schema.*; + +@TargetObjectSchemaInfo( + name = "ExecutionFilter", + elements = { + @TargetElementType(type = Void.class) }, + attributes = { + @TargetAttributeType(type = Object.class) }) +public class DbgModelTargetExecutionOptionImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetEventOption { + + private DbgModelTargetEvent event; + private DebugFilterExecutionOption optionExc; + + public DbgModelTargetExecutionOptionImpl(DbgModelTargetEvent event, + DebugFilterExecutionOption option) { + super(event.getModel(), event, "Execute", "ExecutionFilter"); + this.event = event; + this.getModel().addModelObject(option, this); + this.optionExc = option; + setAttributes(); + } + + public DbgModelTargetExecutionOptionImpl(DbgModelTargetException exc, + DebugFilterExecutionOption option) { + super(exc.getModel(), exc, "Execute", "ExecutionFilter"); + this.event = exc; + this.getModel().addModelObject(option, this); + this.optionExc = option; + setAttributes(); + } + + @Override + public CompletableFuture disable() { + return enable(); + } + + @Override + public CompletableFuture enable() { + DbgManagerImpl manager = getManager(); + int ordinal = (optionExc.ordinal() + 1) % (DebugFilterExecutionOption.values().length - 1); + optionExc = DebugFilterExecutionOption.getByNumber(ordinal); + setAttributes(); + return manager.execute( + new DbgToggleExecutionCommand(manager, event.getEventIndex(), optionExc)); + } + + public void setAttributes() { + changeAttributes(List.of(), List.of(), Map.of( // + DISPLAY_ATTRIBUTE_NAME, getName() + " : " + optionExc.description, // + VALUE_ATTRIBUTE_NAME, optionExc, // + ENABLED_ATTRIBUTE_NAME, + optionExc.equals(DebugFilterExecutionOption.DEBUG_FILTER_BREAK)), "Refreshed"); + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java index 9b708f990b..48b4900954 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java @@ -182,6 +182,11 @@ public class DbgModel2Impl extends AbstractDbgModel return objectMap.get(object); } + @Override + public void deleteModelObject(Object object) { + objectMap.remove(object); + } + @Override public CompletableFuture gateFuture(CompletableFuture future) { return super.gateFuture(future).exceptionally(ex -> { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java index 67047d5f53..e54e947418 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java @@ -1210,6 +1210,22 @@ public interface DebuggerResources { } } + abstract class AbstractToggleAction extends DockingAction { + public static final String NAME = "Toggle"; + public static final Icon ICON = ICON_BREAKPOINT_MIXED_ED_MARKER; + public static final String HELP_ANCHOR = "toggle_option"; + + public static HelpLocation help(Plugin owner) { + return new HelpLocation(owner.getName(), HELP_ANCHOR); + } + + public AbstractToggleAction(Plugin owner) { + super(NAME, owner.getName()); + setDescription("Enable or disable an option"); + setHelpLocation(new HelpLocation(owner.getName(), HELP_ANCHOR)); + } + } + interface MapIdenticallyAction { String NAME = "Map Identically"; String DESCRIPTION = diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index d0fc11fc8d..fd413e7f3a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -1148,43 +1148,43 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter groupTargetIndex++; new ActionBuilder("Finish", plugin.getName()) - .keyBinding("F12") - .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .toolBarIcon(AbstractStepFinishAction.ICON) - .popupMenuPath("&Finish") - .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .popupMenuIcon(AbstractStepFinishAction.ICON) - .helpLocation(AbstractStepFinishAction.help(plugin)) - //.withContext(ObjectActionContext.class) - .enabledWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .popupWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .onAction(ctx -> performStepFinish(ctx)) - .enabled(false) - .buildAndInstallLocal(this); + .keyBinding("F12") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .toolBarIcon(AbstractStepFinishAction.ICON) + .popupMenuPath("&Finish") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .popupMenuIcon(AbstractStepFinishAction.ICON) + .helpLocation(AbstractStepFinishAction.help(plugin)) + //.withContext(ObjectActionContext.class) + .enabledWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .popupWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .onAction(ctx -> performStepFinish(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; + + new ActionBuilder("Step Last", plugin.getName()) + .keyBinding("ALT F8") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .toolBarIcon(AbstractStepLastAction.ICON) + .popupMenuPath("&Step Last") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .popupMenuIcon(AbstractStepLastAction.ICON) + .helpLocation(AbstractStepLastAction.help(plugin)) + //.withContext(ObjectActionContext.class) + .enabledWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .popupWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .onAction(ctx -> performStepLast(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; - groupTargetIndex++; - - new ActionBuilder("Step Last", plugin.getName()) - .keyBinding("ALT F8") - .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .toolBarIcon(AbstractStepLastAction.ICON) - .popupMenuPath("&Step Last") - .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .popupMenuIcon(AbstractStepLastAction.ICON) - .helpLocation(AbstractStepLastAction.help(plugin)) - //.withContext(ObjectActionContext.class) - .enabledWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .popupWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .onAction(ctx -> performStepLast(ctx)) - .enabled(false) - .buildAndInstallLocal(this); - - groupTargetIndex++; - actionAddBreakpoint = new ActionBuilder("Add Breakpoint", plugin.getName()) .keyBinding("F3") .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) @@ -1221,6 +1221,20 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter groupTargetIndex++; + new ActionBuilder("Toggle", plugin.getName()) + .keyBinding("T") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) + .popupMenuPath("&Toggle") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) + .helpLocation(AbstractToggleAction.help(plugin)) + .enabledWhen(ctx -> isInstance(ctx, TargetTogglable.class)) + .popupWhen(ctx -> isInstance(ctx, TargetResumable.class)) + .onAction(ctx -> performToggle(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; + displayAsTreeAction = new DisplayAsTreeAction(tool, plugin.getName(), this); displayAsTableAction = new DisplayAsTableAction(tool, plugin.getName(), this); displayAsGraphAction = new DisplayAsGraphAction(tool, plugin.getName(), this); @@ -1486,6 +1500,12 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter }, "Couldn't set breakpoint"); } + public void performToggle(ActionContext context) { + performAction(context, false, TargetTogglable.class, t -> { + return t.toggle(!t.isEnabled()); + }, "Couldn't toggle"); + } + public void initiateConsole(ActionContext context) { performAction(context, false, TargetInterpreter.class, interpreter -> { getPlugin().showConsole(interpreter);