diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java index 9bb1c881ff..301f7d70c5 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java @@ -22,7 +22,6 @@ import ghidra.dbg.target.TargetBreakpointLocation; import ghidra.program.model.address.Address; import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.thread.TraceThread; -import ghidra.util.Msg; import ghidra.util.database.UndoableTransaction; public class BreakpointLocationRow { @@ -43,17 +42,18 @@ public class BreakpointLocationRow { } public void setEnabled(boolean enabled) { + // TODO: Make this toggle the individual location, if possible, not the whole spec. TraceRecorder recorder = provider.modelService.getRecorder(loc.getTrace()); TargetBreakpointLocation bpt = recorder.getTargetBreakpoint(loc); if (enabled) { bpt.getSpecification().enable().exceptionally(ex -> { - Msg.showError(this, null, "Toggle breakpoint", "Could not enable breakpoint", ex); + provider.breakpointError("Toggle breakpoint", "Could not enable breakpoint", ex); return null; }); } else { bpt.getSpecification().disable().exceptionally(ex -> { - Msg.showError(this, null, "Toggle breakpoint", "Could not disable breakpoint", ex); + provider.breakpointError("Toggle breakpoint", "Could not disable breakpoint", ex); return null; }); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java index 4ba11b3cca..e25d603d85 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java @@ -532,7 +532,7 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin if (bs == null || bs.isEmpty()) { Set supported = getSupportedKindsFromContext(context); if (supported.isEmpty()) { - Msg.showError(this, null, NAME, + breakpointError(NAME, "It seems this target does not support breakpoints."); return; } @@ -545,13 +545,13 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin Trace trace = getTraceFromContext(context); // OK if null - means all traces if (en.enabled) { breakpointService.disableAll(bs, trace).exceptionally(ex -> { - Msg.showError(this, null, NAME, "Could not disable breakpoints", ex); + breakpointError(NAME, "Could not disable breakpoints", ex); return null; }); } else { breakpointService.enableAll(bs, trace).exceptionally(ex -> { - Msg.showError(this, null, NAME, "Could not enable breakpoints", ex); + breakpointError(NAME, "Could not enable breakpoints", ex); return null; }); } @@ -628,7 +628,7 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin ProgramLocation location = getLocationFromContext(context); Set col = breakpointService.getBreakpointsAt(location); breakpointService.enableAll(col, getTraceFromContext(context)).exceptionally(ex -> { - Msg.showError(this, null, NAME, "Could not enable breakpoint", ex); + breakpointError(NAME, "Could not enable breakpoint", ex); return null; }); } @@ -665,7 +665,7 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin ProgramLocation location = getLocationFromContext(context); Set col = breakpointService.getBreakpointsAt(location); breakpointService.disableAll(col, getTraceFromContext(context)).exceptionally(ex -> { - Msg.showError(this, null, NAME, "Could not disable breakpoint", ex); + breakpointError(NAME, "Could not disable breakpoint", ex); return null; }); } @@ -704,7 +704,7 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin ProgramLocation location = getLocationFromContext(context); Set col = breakpointService.getBreakpointsAt(location); breakpointService.deleteAll(col, getTraceFromContext(context)).exceptionally(ex -> { - Msg.showError(this, null, NAME, "Could not delete breakpoint", ex); + breakpointError(NAME, "Could not delete breakpoint", ex); return null; }); } @@ -733,6 +733,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin private DebuggerStaticMappingService mappingService; @AutoServiceConsumed private DebuggerTraceManagerService traceManager; + @AutoServiceConsumed + private DebuggerConsoleService consoleService; @SuppressWarnings("unused") private final AutoService.Wiring autoServiceWiring; @@ -1084,4 +1086,21 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin } } } + + protected void breakpointError(String title, String message) { + if (consoleService == null) { + Msg.showError(this, null, title, message); + return; + } + consoleService.log(DebuggerResources.ICON_LOG_ERROR, message); + } + + protected void breakpointError(String title, String message, Throwable ex) { + if (consoleService == null) { + Msg.showError(this, null, title, message, ex); + return; + } + Msg.error(this, message, ex); + consoleService.log(DebuggerResources.ICON_LOG_ERROR, message + " (" + ex + ")"); + } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java index c8f49fe2d8..3a613f554d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java @@ -254,8 +254,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter (DebuggerLogicalBreakpointsActionContext) context; Collection sel = ctx.getSelection(); breakpointService.enableAll(sel, null).exceptionally(ex -> { - Msg.showError(this, getComponent(), "Enable Breakpoints", - "Could not enable breakpoints", ex); + breakpointError("Enable Breakpoints", "Could not enable breakpoints", ex); return null; }); } @@ -286,8 +285,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter public void actionPerformed(ActionContext context) { Set all = breakpointService.getAllBreakpoints(); breakpointService.enableAll(all, null).exceptionally(ex -> { - Msg.showError(this, getComponent(), "Enable All Breakpoints", - "Could not enable breakpoints", ex); + breakpointError("Enable All Breakpoints", "Could not enable breakpoints", ex); return null; }); } @@ -320,8 +318,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter (DebuggerLogicalBreakpointsActionContext) context; Collection sel = ctx.getSelection(); breakpointService.disableAll(sel, null).exceptionally(ex -> { - Msg.showError(this, getComponent(), "Disable Breakpoints", - "Could not disable breakpoints", ex); + breakpointError("Disable Breakpoints", "Could not disable breakpoints", ex); return null; }); } @@ -352,8 +349,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter public void actionPerformed(ActionContext context) { Set all = breakpointService.getAllBreakpoints(); breakpointService.disableAll(all, null).exceptionally(ex -> { - Msg.showError(this, getComponent(), "Disable All Breakpoints", - "Could not disable breakpoints", ex); + breakpointError("Disable All Breakpoints", "Could not disable breakpoints", ex); return null; }); } @@ -382,8 +378,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter (DebuggerLogicalBreakpointsActionContext) context; Collection sel = ctx.getSelection(); breakpointService.deleteAll(sel, null).exceptionally(ex -> { - Msg.showError(this, getComponent(), "Clear Breakpoints", - "Could not clear breakpoints", ex); + breakpointError("Clear Breakpoints", "Could not clear breakpoints", ex); return null; }); } @@ -414,8 +409,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter public void actionPerformed(ActionContext context) { Set all = breakpointService.getAllBreakpoints(); breakpointService.deleteAll(all, null).exceptionally(ex -> { - Msg.showError(this, getComponent(), "Clear All Breakpoints", - "Could not clear breakpoints", ex); + breakpointError("Clear All Breakpoints", "Could not clear breakpoints", ex); return null; }); } @@ -598,7 +592,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter // @AutoServiceConsumed via method private DebuggerLogicalBreakpointService breakpointService; - // @AutoServiceConsumed via method + // @AutoServiceConsumed via method, package access for BreakpointLogicalRow DebuggerModelService modelService; @AutoServiceConsumed private DebuggerListingService listingService; @@ -1085,4 +1079,13 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable, locationTableModel, locationFilterPanel); } + + protected void breakpointError(String title, String message, Throwable ex) { + if (consoleService == null) { + Msg.showError(this, null, title, message, ex); + return; + } + Msg.error(this, message, ex); + consoleService.log(DebuggerResources.ICON_LOG_ERROR, message + " (" + ex + ")"); + } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/LogicalBreakpointRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/LogicalBreakpointRow.java index 486f245cde..2b774d3130 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/LogicalBreakpointRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/LogicalBreakpointRow.java @@ -24,7 +24,6 @@ import ghidra.framework.model.DomainObject; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; -import ghidra.util.Msg; public class LogicalBreakpointRow { private final DebuggerBreakpointsProvider provider; @@ -64,7 +63,7 @@ public class LogicalBreakpointRow { ? lb.enableForTrace(provider.currentTrace) : lb.enable(); future.exceptionally(ex -> { - Msg.showError(this, null, "Toggle Breakpoint", "Could not enable breakpoint", ex); + provider.breakpointError("Toggle Breakpoint", "Could not enable breakpoint", ex); return null; }); } @@ -73,7 +72,7 @@ public class LogicalBreakpointRow { ? lb.disableForTrace(provider.currentTrace) : lb.disable(); future.exceptionally(ex -> { - Msg.showError(this, null, "Toggle Breakpoint", "Could not disable breakpoint", ex); + provider.breakpointError("Toggle Breakpoint", "Could not disable breakpoint", ex); return null; }); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsolePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsolePlugin.java index 310f873049..eef802210f 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsolePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsolePlugin.java @@ -100,6 +100,11 @@ public class DebuggerConsolePlugin extends Plugin implements DebuggerConsoleServ super.dispose(); } + @Override + public void log(Icon icon, String message) { + provider.log(icon, message); + } + @Override public void log(Icon icon, String message, ActionContext context) { provider.log(icon, message, context); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java index fc6dfabe78..9fb446e832 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java @@ -56,7 +56,7 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter static final int ACTION_BUTTON_SIZE = 32; static final Dimension ACTION_BUTTON_DIM = new Dimension(ACTION_BUTTON_SIZE, ACTION_BUTTON_SIZE); - static final int MAX_ROW_HEIGHT = 300; + static final int MIN_ROW_HEIGHT = 16; protected enum LogTableColumns implements EnumeratedTableColumn { LEVEL("Level", Icon.class, LogRow::getIcon, SortDirection.ASCENDING, false), @@ -242,7 +242,7 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter int rows = model.getRowCount(); int cols = getColumnCount(); for (int r = 0; r < rows; r++) { - int height = 0; + int height = MIN_ROW_HEIGHT; for (int c = 0; c < cols; c++) { height = Math.max(height, computePreferredHeight(r, c)); } @@ -400,6 +400,10 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter } } + protected void log(Icon icon, String message) { + log(icon, message, new LogRowConsoleActionContext()); + } + protected void log(Icon icon, String message, ActionContext context) { logRow(new LogRow(icon, message, new Date(), context, computeToolbarActions(context))); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerConsoleService.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerConsoleService.java index e356edca0a..beb7713279 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerConsoleService.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerConsoleService.java @@ -27,6 +27,17 @@ import ghidra.util.HTMLUtilities; @ServiceInfo(defaultProvider = DebuggerConsolePlugin.class) public interface DebuggerConsoleService extends DebuggerConsoleLogger { + /** + * Log a message to the console + * + *

+ * WARNING: See {@link #log(Icon, String, ActionContext)} regarding HTML. + * + * @param icon an icon for the message + * @param message the HTML-formatted message + */ + void log(Icon icon, String message); + /** * Log an actionable message to the console *