mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-4334: Remove 'Synchronize Target Activation' toggle. Prohibit time navigation in Target mode.
This commit is contained in:
@@ -303,7 +303,7 @@ public interface DebuggerTraceManagerService {
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If asynchronous notification is needed, use
|
* If asynchronous notification is needed, use
|
||||||
* {@link #activateAndNotify(DebuggerCoordinates, boolean)}.
|
* {@link #activateAndNotify(DebuggerCoordinates, ActivationCause)}.
|
||||||
*
|
*
|
||||||
* @param coordinates the desired coordinates
|
* @param coordinates the desired coordinates
|
||||||
* @param cause the cause of activation
|
* @param cause the cause of activation
|
||||||
@@ -484,34 +484,6 @@ public interface DebuggerTraceManagerService {
|
|||||||
activate(resolveObject(object));
|
activate(resolveObject(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Control whether trace activation is synchronized with debugger activation
|
|
||||||
*
|
|
||||||
* @param enabled true to synchronize, false otherwise
|
|
||||||
*/
|
|
||||||
void setSynchronizeActive(boolean enabled);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether trace activation is synchronized with debugger activation
|
|
||||||
*
|
|
||||||
* @return true if synchronized, false otherwise
|
|
||||||
*/
|
|
||||||
boolean isSynchronizeActive();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener for changes to activation synchronization enablement
|
|
||||||
*
|
|
||||||
* @param listener the listener to receive change notifications
|
|
||||||
*/
|
|
||||||
void addSynchronizeActiveChangeListener(BooleanChangeAdapter listener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a listener for changes to activation synchronization enablement
|
|
||||||
*
|
|
||||||
* @param listener the listener receiving change notifications
|
|
||||||
*/
|
|
||||||
void removeSynchronizeActiveChangeListener(BooleanChangeAdapter listener);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control whether traces should be saved by default
|
* Control whether traces should be saved by default
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -90,23 +90,10 @@ public enum ControlMode {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ControlMode modeOnChange(DebuggerCoordinates coordinates) {
|
|
||||||
if (coordinates.isAliveAndPresent()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return getAlternative(coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSelectable(DebuggerCoordinates coordinates) {
|
public boolean isSelectable(DebuggerCoordinates coordinates) {
|
||||||
return coordinates.isAlive();
|
return coordinates.isAlive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ControlMode getAlternative(DebuggerCoordinates coordinates) {
|
|
||||||
return RO_TRACE;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Control actions, breakpoint commands, and state edits are all directed to the target.
|
* Control actions, breakpoint commands, and state edits are all directed to the target.
|
||||||
@@ -159,23 +146,10 @@ public enum ControlMode {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ControlMode modeOnChange(DebuggerCoordinates coordinates) {
|
|
||||||
if (coordinates.isAliveAndPresent()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return getAlternative(coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSelectable(DebuggerCoordinates coordinates) {
|
public boolean isSelectable(DebuggerCoordinates coordinates) {
|
||||||
return coordinates.isAlive();
|
return coordinates.isAlive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ControlMode getAlternative(DebuggerCoordinates coordinates) {
|
|
||||||
return RW_EMULATOR;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Control actions activate trace snapshots, breakpoint commands are directed to the emulator,
|
* Control actions activate trace snapshots, breakpoint commands are directed to the emulator,
|
||||||
@@ -391,6 +365,38 @@ public enum ControlMode {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean followsPresent();
|
public abstract boolean followsPresent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and/or adjust the given coordinates pre-activation
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This is called by the trace manager whenever there is a request to activate new coordinates.
|
||||||
|
* The control mode may adjust or reject the request before the trace manager actually performs
|
||||||
|
* and notifies the activation.
|
||||||
|
*
|
||||||
|
* @param tool the tool for displaying status messages
|
||||||
|
* @param coordinates the requested coordinates
|
||||||
|
* @param cause the cause of the activation
|
||||||
|
* @return the effective coordinates or null to reject
|
||||||
|
*/
|
||||||
|
public DebuggerCoordinates validateCoordinates(PluginTool tool,
|
||||||
|
DebuggerCoordinates coordinates, ActivationCause cause) {
|
||||||
|
if (!followsPresent()) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
Target target = coordinates.getTarget();
|
||||||
|
if (target == null) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
if (cause == ActivationCause.USER &&
|
||||||
|
(!coordinates.getTime().isSnapOnly() || coordinates.getSnap() != target.getSnap())) {
|
||||||
|
tool.setStatusInfo(
|
||||||
|
"Cannot navigate time in %s mode. Switch to Trace or Emulate mode first."
|
||||||
|
.formatted(name),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
return coordinates.snap(target.getSnap());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if (broadly speaking) the mode supports editing the given coordinates
|
* Check if (broadly speaking) the mode supports editing the given coordinates
|
||||||
*
|
*
|
||||||
@@ -444,37 +450,6 @@ public enum ControlMode {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If the mode can no longer be selected for new coordinates, get the new mode
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For example, if a target terminates while the mode is {@link #RO_TARGET}, this specifies the
|
|
||||||
* new mode.
|
|
||||||
*
|
|
||||||
* @param coordinates the new coordinates
|
|
||||||
* @return the new mode
|
|
||||||
*/
|
|
||||||
public ControlMode getAlternative(DebuggerCoordinates coordinates) {
|
|
||||||
throw new AssertionError("INTERNAL: Non-selectable mode must provide alternative");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the new mode (or same) mode when activating the given coordinates
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The default is implemented using {@link #isSelectable(DebuggerCoordinates)} followed by
|
|
||||||
* {@link #getAlternative(DebuggerCoordinates)}.
|
|
||||||
*
|
|
||||||
* @param coordinates the new coordinates
|
|
||||||
* @return the mode
|
|
||||||
*/
|
|
||||||
public ControlMode modeOnChange(DebuggerCoordinates coordinates) {
|
|
||||||
if (isSelectable(coordinates)) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return getAlternative(coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether this mode controls the target
|
* Indicates whether this mode controls the target
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -480,6 +480,8 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
private DebuggerControlService controlService;
|
private DebuggerControlService controlService;
|
||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
|
private DebuggerConsoleService consoleService;
|
||||||
|
@AutoServiceConsumed
|
||||||
private MarkerService markerService; // TODO: Mark address types (separate plugin?)
|
private MarkerService markerService; // TODO: Mark address types (separate plugin?)
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final AutoService.Wiring autoServiceWiring;
|
private final AutoService.Wiring autoServiceWiring;
|
||||||
@@ -847,15 +849,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||||||
CompletableFuture<Void> future = editor.setRegister(rv);
|
CompletableFuture<Void> future = editor.setRegister(rv);
|
||||||
future.exceptionally(ex -> {
|
future.exceptionally(ex -> {
|
||||||
ex = AsyncUtils.unwrapThrowable(ex);
|
ex = AsyncUtils.unwrapThrowable(ex);
|
||||||
if (ex instanceof DebuggerModelAccessException) {
|
reportError("Edit Register", "Could not write target register", ex);
|
||||||
Msg.error(this, "Could not write target register", ex);
|
|
||||||
plugin.getTool()
|
|
||||||
.setStatusInfo("Could not write target register: " + ex.getMessage());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Msg.showError(this, getComponent(), "Edit Register",
|
|
||||||
"Could not write target register", ex);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -1278,9 +1272,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||||||
current.getThread(), current.getFrame(), registers);
|
current.getThread(), current.getFrame(), registers);
|
||||||
return future.exceptionally(ex -> {
|
return future.exceptionally(ex -> {
|
||||||
ex = AsyncUtils.unwrapThrowable(ex);
|
ex = AsyncUtils.unwrapThrowable(ex);
|
||||||
String msg = "Could not read target registers for selected thread: " + ex.getMessage();
|
reportError(null, "Could not read target registers for selected thread", ex);
|
||||||
Msg.info(this, msg);
|
|
||||||
plugin.getTool().setStatusInfo(msg);
|
|
||||||
return ExceptionUtils.rethrow(ex);
|
return ExceptionUtils.rethrow(ex);
|
||||||
}).thenApply(__ -> null);
|
}).thenApply(__ -> null);
|
||||||
}
|
}
|
||||||
@@ -1301,4 +1293,17 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||||||
public DebuggerCoordinates getCurrent() {
|
public DebuggerCoordinates getCurrent() {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reportError(String title, String message, Throwable ex) {
|
||||||
|
plugin.getTool().setStatusInfo(message + ": " + ex.getMessage());
|
||||||
|
if (title != null && !(ex instanceof DebuggerModelAccessException)) {
|
||||||
|
Msg.showError(this, getComponent(), title, message, ex);
|
||||||
|
}
|
||||||
|
else if (consoleService != null) {
|
||||||
|
consoleService.log(DebuggerResources.ICON_LOG_ERROR, message, ex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Msg.error(this, message, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,10 @@ import org.apache.commons.lang3.ArrayUtils;
|
|||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.WindowPosition;
|
import docking.WindowPosition;
|
||||||
import docking.action.*;
|
import docking.action.DockingActionIf;
|
||||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.SynchronizeTargetAction;
|
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.ToToggleSelectionListener;
|
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService.BooleanChangeAdapter;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.model.DomainObjectChangeRecord;
|
import ghidra.framework.model.DomainObjectChangeRecord;
|
||||||
import ghidra.framework.model.DomainObjectEvent;
|
import ghidra.framework.model.DomainObjectEvent;
|
||||||
@@ -97,18 +94,14 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
|||||||
final DebuggerThreadsPlugin plugin;
|
final DebuggerThreadsPlugin plugin;
|
||||||
|
|
||||||
DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
||||||
Trace currentTrace; // Copy for transition
|
|
||||||
|
|
||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
DebuggerTargetService targetService;
|
DebuggerTargetService targetService;
|
||||||
// @AutoServiceConsumed by method
|
// @AutoServiceConsumed // via method
|
||||||
private DebuggerTraceManagerService traceManager;
|
private DebuggerTraceManagerService traceManager;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final AutoService.Wiring autoServiceWiring;
|
private final AutoService.Wiring autoServiceWiring;
|
||||||
|
|
||||||
private final BooleanChangeAdapter synchronizeTargetChangeListener =
|
|
||||||
this::changedSynchronizeTarget;
|
|
||||||
|
|
||||||
private final ForSnapsListener forSnapsListener = new ForSnapsListener();
|
private final ForSnapsListener forSnapsListener = new ForSnapsListener();
|
||||||
|
|
||||||
private JPanel mainPanel;
|
private JPanel mainPanel;
|
||||||
@@ -118,15 +111,8 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
|||||||
DebuggerThreadsPanel panel;
|
DebuggerThreadsPanel panel;
|
||||||
DebuggerLegacyThreadsPanel legacyPanel;
|
DebuggerLegacyThreadsPanel legacyPanel;
|
||||||
|
|
||||||
DockingAction actionSaveTrace;
|
|
||||||
// TODO: This should probably be moved to ModelProvider
|
|
||||||
ToggleDockingAction actionSyncTarget;
|
|
||||||
|
|
||||||
ActionContext myActionContext;
|
ActionContext myActionContext;
|
||||||
|
|
||||||
// strong ref
|
|
||||||
ToToggleSelectionListener toToggleSelectionListener;
|
|
||||||
|
|
||||||
public DebuggerThreadsProvider(final DebuggerThreadsPlugin plugin) {
|
public DebuggerThreadsProvider(final DebuggerThreadsPlugin plugin) {
|
||||||
super(plugin.getTool(), DebuggerResources.TITLE_PROVIDER_THREADS, plugin.getName());
|
super(plugin.getTool(), DebuggerResources.TITLE_PROVIDER_THREADS, plugin.getName());
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -149,17 +135,7 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
|||||||
|
|
||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
public void setTraceManager(DebuggerTraceManagerService traceManager) {
|
public void setTraceManager(DebuggerTraceManagerService traceManager) {
|
||||||
if (this.traceManager != null) {
|
|
||||||
this.traceManager
|
|
||||||
.removeSynchronizeActiveChangeListener(synchronizeTargetChangeListener);
|
|
||||||
}
|
|
||||||
this.traceManager = traceManager;
|
this.traceManager = traceManager;
|
||||||
if (traceManager != null) {
|
|
||||||
traceManager.addSynchronizeActiveChangeListener(synchronizeTargetChangeListener);
|
|
||||||
if (actionSyncTarget != null) {
|
|
||||||
actionSyncTarget.setSelected(traceManager.isSynchronizeActive());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contextChanged();
|
contextChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,27 +218,6 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void createActions() {
|
protected void createActions() {
|
||||||
actionSyncTarget = SynchronizeTargetAction.builder(plugin)
|
|
||||||
.selected(traceManager != null && traceManager.isSynchronizeActive())
|
|
||||||
.enabledWhen(c -> traceManager != null)
|
|
||||||
.onAction(c -> toggleSyncFocus(actionSyncTarget.isSelected()))
|
|
||||||
.buildAndInstallLocal(this);
|
|
||||||
traceManager.addSynchronizeActiveChangeListener(
|
|
||||||
toToggleSelectionListener = new ToToggleSelectionListener(actionSyncTarget));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void changedSynchronizeTarget(boolean value) {
|
|
||||||
if (actionSyncTarget == null || actionSyncTarget.isSelected()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
actionSyncTarget.setSelected(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleSyncFocus(boolean enabled) {
|
|
||||||
if (traceManager == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
traceManager.setSynchronizeActive(enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import java.util.concurrent.*;
|
|||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.plugin.core.debug.AbstractDebuggerPlugin;
|
import ghidra.app.plugin.core.debug.AbstractDebuggerPlugin;
|
||||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||||
import ghidra.app.plugin.core.debug.event.*;
|
import ghidra.app.plugin.core.debug.event.TraceClosedPluginEvent;
|
||||||
|
import ghidra.app.plugin.core.debug.event.TraceOpenedPluginEvent;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
|
|
||||||
import ghidra.debug.api.control.ControlMode;
|
import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
@@ -46,7 +46,6 @@ import ghidra.util.datastruct.ListenerSet;
|
|||||||
status = PluginStatus.RELEASED,
|
status = PluginStatus.RELEASED,
|
||||||
eventsConsumed = {
|
eventsConsumed = {
|
||||||
TraceOpenedPluginEvent.class,
|
TraceOpenedPluginEvent.class,
|
||||||
TraceActivatedPluginEvent.class,
|
|
||||||
TraceClosedPluginEvent.class,
|
TraceClosedPluginEvent.class,
|
||||||
},
|
},
|
||||||
servicesRequired = {
|
servicesRequired = {
|
||||||
@@ -263,29 +262,6 @@ public class DebuggerControlServicePlugin extends AbstractDebuggerPlugin
|
|||||||
return new FollowsViewStateEditor(view);
|
return new FollowsViewStateEditor(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void coordinatesActivated(DebuggerCoordinates coordinates, ActivationCause cause) {
|
|
||||||
if (cause != ActivationCause.USER) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Trace trace = coordinates.getTrace();
|
|
||||||
if (trace == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ControlMode oldMode;
|
|
||||||
ControlMode newMode;
|
|
||||||
synchronized (currentModes) {
|
|
||||||
oldMode = currentModes.getOrDefault(trace, ControlMode.DEFAULT);
|
|
||||||
newMode = oldMode.modeOnChange(coordinates);
|
|
||||||
if (newMode != oldMode) {
|
|
||||||
currentModes.put(trace, newMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newMode != oldMode) {
|
|
||||||
listeners.invoke().modeChanged(trace, newMode);
|
|
||||||
tool.contextChanged(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void installMemoryEditor(TraceProgramView view) {
|
protected void installMemoryEditor(TraceProgramView view) {
|
||||||
TraceProgramViewMemory memory = view.getMemory();
|
TraceProgramViewMemory memory = view.getMemory();
|
||||||
if (memory.getLiveMemoryHandler() != null) {
|
if (memory.getLiveMemoryHandler() != null) {
|
||||||
@@ -346,9 +322,6 @@ public class DebuggerControlServicePlugin extends AbstractDebuggerPlugin
|
|||||||
if (event instanceof TraceOpenedPluginEvent ev) {
|
if (event instanceof TraceOpenedPluginEvent ev) {
|
||||||
installAllMemoryEditors(ev.getTrace());
|
installAllMemoryEditors(ev.getTrace());
|
||||||
}
|
}
|
||||||
else if (event instanceof TraceActivatedPluginEvent ev) {
|
|
||||||
coordinatesActivated(ev.getActiveCoordinates(), ev.getCause());
|
|
||||||
}
|
|
||||||
else if (event instanceof TraceClosedPluginEvent ev) {
|
else if (event instanceof TraceClosedPluginEvent ev) {
|
||||||
uninstallAllMemoryEditors(ev.getTrace());
|
uninstallAllMemoryEditors(ev.getTrace());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
DebuggerCoordinates coords = current;
|
DebuggerCoordinates coords = current;
|
||||||
TraceObjectKeyPath focus = curTarget.getFocus();
|
TraceObjectKeyPath focus = curTarget.getFocus();
|
||||||
if (focus != null && synchronizeActive.get()) {
|
if (focus != null) {
|
||||||
coords = coords.path(focus);
|
coords = coords.path(focus);
|
||||||
}
|
}
|
||||||
coords = coords.snap(curTarget.getSnap());
|
coords = coords.snap(curTarget.getSnap());
|
||||||
@@ -274,8 +274,6 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
||||||
protected final AsyncReference<Boolean, Void> saveTracesByDefault = new AsyncReference<>(true);
|
protected final AsyncReference<Boolean, Void> saveTracesByDefault = new AsyncReference<>(true);
|
||||||
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
||||||
protected final AsyncReference<Boolean, Void> synchronizeActive = new AsyncReference<>(true);
|
|
||||||
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
|
||||||
protected final AsyncReference<Boolean, Void> autoCloseOnTerminate = new AsyncReference<>(true);
|
protected final AsyncReference<Boolean, Void> autoCloseOnTerminate = new AsyncReference<>(true);
|
||||||
|
|
||||||
// @AutoServiceConsumed via method
|
// @AutoServiceConsumed via method
|
||||||
@@ -569,6 +567,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
newCurrent = newCurrent.snap(target.getSnap());
|
newCurrent = newCurrent.snap(target.getSnap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newCurrent = validateCoordiantes(newCurrent, cause);
|
||||||
if (!doSetCurrent(newCurrent)) {
|
if (!doSetCurrent(newCurrent)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -583,10 +582,21 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
tool.contextChanged(null);
|
tool.contextChanged(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ControlMode getEffectiveControlMode(Trace trace) {
|
||||||
|
if (trace == null) {
|
||||||
|
return ControlMode.RO_TRACE;
|
||||||
|
}
|
||||||
|
return controlService == null ? ControlMode.DEFAULT : controlService.getCurrentMode(trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DebuggerCoordinates validateCoordiantes(DebuggerCoordinates coordinates,
|
||||||
|
ActivationCause cause) {
|
||||||
|
ControlMode mode = getEffectiveControlMode(coordinates.getTrace());
|
||||||
|
return mode.validateCoordinates(tool, coordinates, cause);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isFollowsPresent(Trace trace) {
|
private boolean isFollowsPresent(Trace trace) {
|
||||||
ControlMode mode = controlService == null
|
ControlMode mode = getEffectiveControlMode(trace);
|
||||||
? ControlMode.DEFAULT
|
|
||||||
: controlService.getCurrentMode(trace);
|
|
||||||
return mode.followsPresent();
|
return mode.followsPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,9 +638,6 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DebuggerCoordinates toActivate = current.target(target);
|
DebuggerCoordinates toActivate = current.target(target);
|
||||||
if (isFollowsPresent(current.getTrace())) {
|
|
||||||
toActivate = toActivate.snap(target.getSnap());
|
|
||||||
}
|
|
||||||
activate(toActivate, ActivationCause.FOLLOW_PRESENT);
|
activate(toActivate, ActivationCause.FOLLOW_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1043,19 +1050,12 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!synchronizeActive.get() && cause == ActivationCause.SYNC_MODEL) {
|
|
||||||
return AsyncUtils.nil();
|
|
||||||
}
|
|
||||||
if (cause == ActivationCause.FOLLOW_PRESENT) {
|
if (cause == ActivationCause.FOLLOW_PRESENT) {
|
||||||
if (!isFollowsPresent(newTrace)) {
|
if (!isFollowsPresent(newTrace)) {
|
||||||
return AsyncUtils.nil();
|
return AsyncUtils.nil();
|
||||||
}
|
}
|
||||||
if (current.getTrace() != newTrace) {
|
if (current.getTrace() != newTrace) {
|
||||||
/**
|
// The snap needs to match upon re-activating this trace.
|
||||||
* The snap needs to match upon re-activating this trace, lest it look like the user
|
|
||||||
* intentionally navigated to the past. That may cause the control mode to switch
|
|
||||||
* off of "Target."
|
|
||||||
*/
|
|
||||||
try {
|
try {
|
||||||
newTrace.getProgramView().setSnap(coordinates.getViewSnap());
|
newTrace.getProgramView().setSnap(coordinates.getViewSnap());
|
||||||
}
|
}
|
||||||
@@ -1082,7 +1082,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!synchronizeActive.get() || cause != ActivationCause.USER) {
|
if (cause != ActivationCause.USER) {
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
Target target = resolved.getTarget();
|
Target target = resolved.getTarget();
|
||||||
@@ -1152,27 +1152,6 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
return current.object(object);
|
return current.object(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSynchronizeActive(boolean enabled) {
|
|
||||||
synchronizeActive.set(enabled, null);
|
|
||||||
// TODO: Which action to take here, if any?
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSynchronizeActive() {
|
|
||||||
return synchronizeActive.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addSynchronizeActiveChangeListener(BooleanChangeAdapter listener) {
|
|
||||||
synchronizeActive.addChangeListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeSynchronizeActiveChangeListener(BooleanChangeAdapter listener) {
|
|
||||||
synchronizeActive.removeChangeListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSaveTracesByDefault(boolean enabled) {
|
public void setSaveTracesByDefault(boolean enabled) {
|
||||||
saveTracesByDefault.set(enabled, null);
|
saveTracesByDefault.set(enabled, null);
|
||||||
|
|||||||
@@ -397,8 +397,6 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSynchronizeFocusTraceToModel() throws Throwable {
|
public void testSynchronizeFocusTraceToModel() throws Throwable {
|
||||||
assertTrue(traceManager.isSynchronizeActive());
|
|
||||||
|
|
||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
@@ -448,18 +446,10 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
waitForPass(() -> assertEquals(frame0, mb.testModel.session.getFocus()));
|
waitForPass(() -> assertEquals(frame0, mb.testModel.session.getFocus()));
|
||||||
|
|
||||||
traceManager.setSynchronizeActive(false);
|
|
||||||
traceManager.activateFrame(1);
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
waitForPass(() -> assertEquals(frame0, mb.testModel.session.getFocus()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSynchronizeFocusModelToTrace() throws Throwable {
|
public void testSynchronizeFocusModelToTrace() throws Throwable {
|
||||||
assertTrue(traceManager.isSynchronizeActive());
|
|
||||||
|
|
||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
@@ -503,12 +493,5 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
waitOn(mb.testModel.session.requestFocus(frame0));
|
waitOn(mb.testModel.session.requestFocus(frame0));
|
||||||
|
|
||||||
waitForPass(() -> assertEquals(0, traceManager.getCurrentFrame()));
|
waitForPass(() -> assertEquals(0, traceManager.getCurrentFrame()));
|
||||||
|
|
||||||
traceManager.setSynchronizeActive(false);
|
|
||||||
waitOn(mb.testModel.session.requestFocus(frame1));
|
|
||||||
// Not super reliable, but at least wait for it to change in case it does
|
|
||||||
Thread.sleep(200);
|
|
||||||
|
|
||||||
assertEquals(0, traceManager.getCurrentFrame());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user