From 70996c989633f250330401d6d23d8170032ec7f8 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 5 May 2021 11:06:10 -0400 Subject: [PATCH] GP-533: New action in Debugger Interpreter to send interrupt --- .../DebuggerInterpreterPlugin.html | 4 ++++ .../core/debug/gui/DebuggerResources.java | 16 +++++++++++++ ...tractDebuggerWrappedConsoleConnection.java | 24 +++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerInterpreterPlugin/DebuggerInterpreterPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerInterpreterPlugin/DebuggerInterpreterPlugin.html index daea6200f1..e697480995 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerInterpreterPlugin/DebuggerInterpreterPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerInterpreterPlugin/DebuggerInterpreterPlugin.html @@ -42,5 +42,9 @@ immediately upon the associated target interpreter becoming invalid, i.e., the connection was closed. Pinning an interpreter keeps it open, but in a disabled state, so that the buffer can be examined after invalidation.

+ +

Interrupt

+ +

This action is always available. It interrupts the current target's execution.

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 474820fd6b..a254a77e34 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 @@ -645,6 +645,22 @@ public interface DebuggerResources { .helpLocation(new HelpLocation(ownerName, HELP_ANCHOR)); } } + + interface InterpreterInterruptAction { + String NAME = "Interpreter Interrupt"; + String DESCRIPTION = "Send an interrupt through this Interpreter"; + Icon ICON = ICON_TERMINATE; + String HELP_ANCHOR = "interrupt"; + + public static ActionBuilder builder(Plugin owner) { + String ownerName = owner.getName(); + return new ActionBuilder(ownerName, NAME) + .description(DESCRIPTION) + .toolBarIcon(ICON) + .keyBinding("CTRL I") + .helpLocation(new HelpLocation(ownerName, HELP_ANCHOR)); + } + } abstract class AbstractRecordAction extends DockingAction { public static final String NAME = "Record"; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java index 929aac8f2e..587b776435 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java @@ -25,16 +25,18 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.ImageIcon; import docking.ActionContext; +import docking.action.DockingAction; import docking.action.ToggleDockingAction; import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.app.plugin.core.debug.gui.DebuggerResources; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.InterpreterInterruptAction; import ghidra.app.plugin.core.debug.gui.DebuggerResources.PinInterpreterAction; import ghidra.app.plugin.core.interpreter.InterpreterComponentProvider; import ghidra.app.plugin.core.interpreter.InterpreterConsole; import ghidra.dbg.AnnotatedDebuggerAttributeListener; +import ghidra.dbg.DebugModelConventions; +import ghidra.dbg.target.*; import ghidra.dbg.target.TargetConsole.Channel; -import ghidra.dbg.target.TargetInterpreter; -import ghidra.dbg.target.TargetObject; import ghidra.util.Msg; import ghidra.util.Swing; @@ -191,6 +193,11 @@ public abstract class AbstractDebuggerWrappedConsoleConnection futureInterruptible = + DebugModelConventions.suitable(TargetInterruptible.class, targetConsole); + if (futureInterruptible != null) { + futureInterruptible.thenCompose(i -> i.interrupt()) + .thenRun(() -> guiConsole.getOutWriter().println("Interrupt sent")) + .exceptionally(exc -> { + guiConsole.getErrWriter().println("Failed to send Interrupt"); + return null; + }); + } + } + protected void run() { try { while (running.get()) {