GP-1329: Prevent disruptive error dialogs from automatic actions.

This commit is contained in:
Dan 2022-01-18 14:18:06 -05:00
parent 2c386e37fe
commit 17d608f797
23 changed files with 156 additions and 87 deletions

View file

@ -274,9 +274,9 @@ public class DebuggerObjectsPlugin extends AbstractDebuggerPlugin
providers.get(0).readConfigState(saveState);
}
public void objectError(String title, String message) {
public void objectError(String message) {
if (consoleService == null) {
Msg.showError(this, null, title, message);
Msg.error(this, message);
return;
}
consoleService.log(DebuggerResources.ICON_LOG_ERROR, message);

View file

@ -465,7 +465,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
if (pane != null) {
if (currentModel != null) {
currentModel.fetchModelRoot().thenAccept(this::refresh).exceptionally(ex -> {
plugin.objectError("Refresh", "Error refreshing model root");
plugin.objectError("Error refreshing model root");
return null;
});
}
@ -668,7 +668,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
table.setColumns();
// TODO: What with attrs?
}).exceptionally(ex -> {
plugin.objectError("Build Table", "Failed to fetch attributes");
plugin.objectError("Failed to fetch attributes");
return null;
});
}
@ -683,7 +683,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
public void addTargetToMap(ObjectContainer container) {
DebuggerObjectsProvider provider = container.getProvider();
if (!this.equals(provider)) {
plugin.objectError("Add Target", "TargetMap corrupted");
plugin.objectError("TargetMap corrupted");
}
TargetObject targetObject = container.getTargetObject();
if (targetObject != null && !container.isLink()) {

View file

@ -34,7 +34,7 @@ public class ObjectElementRow {
map = attributes;
}).exceptionally(ex -> {
DebuggerObjectsPlugin plugin = provider.getPlugin();
plugin.objectError("Create Row", "Failed to fetch attributes");
plugin.objectError("Failed to fetch attributes");
return null;
});
}

View file

@ -38,6 +38,7 @@ public interface DebuggerModelServiceInternal extends DebuggerModelService {
/**
* Force the set of factory instances to be that given
*
* <p>
* This exists for testing the factory change listeners. A test depending on a controlled
* collection of model factories must invoke this method before said test. Conventionally, it is
* the responsibility of each test to ensure its own preconditions are met. For a test depending
@ -51,6 +52,7 @@ public interface DebuggerModelServiceInternal extends DebuggerModelService {
/**
* Set the model factories back to those found on the classpath
*
* <p>
* This exists for testing the factory change listeners. A test depending on
* classpath-discovered factories must invoke this method. It must consider that a previous test
* may have overridden the factories using {@link #setModelFactories(Collection)}.
@ -65,6 +67,7 @@ public interface DebuggerModelServiceInternal extends DebuggerModelService {
/**
* Start and open a new trace on the given target
*
* <p>
* Starts a new trace, and opens it in the tool
*
* @see #recordTarget(TargetObject)

View file

@ -314,8 +314,8 @@ public class DebuggerModelServicePlugin extends Plugin
}
@Override
public TraceRecorder recordTarget(TargetObject target, DebuggerTargetTraceMapper mapper)
throws IOException {
public TraceRecorder recordTarget(TargetObject target, DebuggerTargetTraceMapper mapper,
ActionSource source) throws IOException {
TraceRecorder recorder;
// Cannot use computeIfAbsent here
// Entry must be present before listeners invoked
@ -328,7 +328,12 @@ public class DebuggerModelServicePlugin extends Plugin
recorder = doBeginRecording(target, mapper);
recorder.addListener(listenerOnRecorders);
recorder.init().exceptionally(e -> {
Msg.showError(this, null, "Record Trace", "Error initializing recorder", e);
if (source == ActionSource.MANUAL) {
Msg.showError(this, null, "Record Trace", "Error initializing recorder", e);
}
else {
Msg.error(this, "Error initializing recorder", e);
}
return null;
});
recordersByTarget.put(target, recorder);
@ -356,7 +361,7 @@ public class DebuggerModelServicePlugin extends Plugin
throw new NoSuchElementException("No mapper for target: " + target);
}
try {
return recordTarget(target, mapper);
return recordTarget(target, mapper, ActionSource.AUTOMATIC);
}
catch (IOException e) {
throw new AssertionError("Could not record target: " + target, e);
@ -383,7 +388,7 @@ public class DebuggerModelServicePlugin extends Plugin
assert selected != null;
DebuggerTargetTraceMapper mapper = selected.take();
try {
return recordTarget(target, mapper);
return recordTarget(target, mapper, ActionSource.MANUAL);
}
catch (IOException e) {
throw new AssertionError("Could not record target: " + target, e);
@ -494,7 +499,7 @@ public class DebuggerModelServicePlugin extends Plugin
public TraceRecorder recordTargetAndActivateTrace(TargetObject target,
DebuggerTargetTraceMapper mapper, DebuggerTraceManagerService traceManager)
throws IOException {
TraceRecorder recorder = recordTarget(target, mapper);
TraceRecorder recorder = recordTarget(target, mapper, ActionSource.AUTOMATIC);
if (traceManager != null) {
Trace trace = recorder.getTrace();
traceManager.openTrace(trace);

View file

@ -63,14 +63,22 @@ import ghidra.util.datastruct.ListenerSet;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@PluginInfo(shortDescription = "Debugger models manager service (proxy to front-end)", description = "Manage debug sessions, connections, and trace recording", category = PluginCategoryNames.DEBUGGER, packageName = DebuggerPluginPackage.NAME, status = PluginStatus.RELEASED, eventsConsumed = {
ProgramActivatedPluginEvent.class,
ProgramClosedPluginEvent.class,
}, servicesRequired = {
DebuggerTraceManagerService.class,
}, servicesProvided = {
DebuggerModelService.class,
})
@PluginInfo(
shortDescription = "Debugger models manager service (proxy to front-end)",
description = "Manage debug sessions, connections, and trace recording",
category = PluginCategoryNames.DEBUGGER,
packageName = DebuggerPluginPackage.NAME,
status = PluginStatus.RELEASED,
eventsConsumed = {
ProgramActivatedPluginEvent.class,
ProgramClosedPluginEvent.class,
},
servicesRequired = {
DebuggerTraceManagerService.class,
},
servicesProvided = {
DebuggerModelService.class,
})
public class DebuggerModelServiceProxyPlugin extends Plugin
implements DebuggerModelServiceInternal {
@ -499,9 +507,9 @@ public class DebuggerModelServiceProxyPlugin extends Plugin
}
@Override
public TraceRecorder recordTarget(TargetObject target, DebuggerTargetTraceMapper mapper)
throws IOException {
return delegate.recordTarget(target, mapper);
public TraceRecorder recordTarget(TargetObject target, DebuggerTargetTraceMapper mapper,
ActionSource source) throws IOException {
return delegate.recordTarget(target, mapper, source);
}
@Override

View file

@ -422,12 +422,14 @@ public class DefaultTraceRecorder implements TraceRecorder {
}
return focusScope.requestFocus(focus).thenApply(__ -> true).exceptionally(ex -> {
ex = AsyncUtils.unwrapThrowable(ex);
String msg = "Could not focus " + focus + ": " + ex.getMessage();
plugin.getTool().setStatusInfo(msg);
if (ex instanceof DebuggerModelAccessException) {
String msg = "Could not focus " + focus + ": " + ex.getMessage();
Msg.info(this, msg);
plugin.getTool().setStatusInfo(msg);
}
Msg.showError(this, null, "Focus Sync", "Could not focus " + focus, ex);
else {
Msg.error(this, "Could not focus " + focus, ex);
}
return false;
});
}

View file

@ -0,0 +1,38 @@
/* ###
* 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 ghidra.app.services;
/**
* Possible sources that drive actions or method invocations
*
* <p>
* This is primarily used to determine where and how errors should be reported. Granted, this is
* only one factor in determining how to deliver an error message. In general, actions which are
* taken automatically should not cause disruptive error messages.
*/
public enum ActionSource {
/**
* The action was requested by the user, usually via a UI action. It is acceptable to display an
* error message.
*/
MANUAL,
/**
* The action was requested automatically, usually by some background thread. Error messages
* should probably be delivered to the log or Debug Console, since displaying an error pop-up
* would seem to "come from nowhere."
*/
AUTOMATIC;
}

View file

@ -108,19 +108,21 @@ public interface DebuggerModelService {
*
* @param target a target to record
* @param mapper a mapper between target and trace objects
* @param source the source of the request
* @return the destination trace
* @throws IOException if a trace cannot be created
* @see DebuggerMappingOpinion#getOffers(TargetObject)
*/
TraceRecorder recordTarget(TargetObject target, DebuggerTargetTraceMapper mapper)
throws IOException;
TraceRecorder recordTarget(TargetObject target, DebuggerTargetTraceMapper mapper,
ActionSource source) throws IOException;
/**
* Query mapping opinions and record the given target using the "best" offer
*
* <p>
* If exactly one offer is given, this simply uses it. If multiple are given, this automatically
* chooses the "best" one without prompting the user. If none are given, this fails.
* chooses the "best" one without prompting the user. If none are given, this fails. This
* invocation is assumed to come from an {@link ActionSource#AUTOMATIC} source.
*
* @see DebuggerMappingOpinion#queryOpinions(TargetObject)
* @param target the target to record.
@ -134,7 +136,8 @@ public interface DebuggerModelService {
* <p>
* Even if exactly one offer is given, the user is prompted to provide information about the new
* recording, and to give the user an opportunity to cancel. If none are given, the prompt says
* as much. If the user cancels, the returned future completes with {@code null}.
* as much. If the user cancels, the returned future completes with {@code null}. The invocation
* is assumed to come from a {@link ActionSource#MANUAL} source.
*
* <p>
* TODO: Should the prompt allow the user to force an opinion which gave no offers?
@ -149,7 +152,8 @@ public interface DebuggerModelService {
* Start and open a new trace on the given target
*
* <p>
* Starts a new trace, and opens it in the tool
* Starts a new trace, and opens it in the tool. The invocation is assumed to come from an
* {@link ActionSource#AUTOMATIC} source.
*
* @see #recordTarget(TargetObject)
*/

View file

@ -116,9 +116,9 @@ public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenera
mb.createTestProcessesAndThreads();
TraceRecorder recorder1 = modelService.recordTarget(mb.testProcess1,
new TestDebuggerTargetTraceMapper(mb.testProcess1));
new TestDebuggerTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
TraceRecorder recorder3 = modelService.recordTarget(mb.testProcess3,
new TestDebuggerTargetTraceMapper(mb.testProcess3));
new TestDebuggerTargetTraceMapper(mb.testProcess3), ActionSource.AUTOMATIC);
Trace trace1 = recorder1.getTrace();
Trace trace3 = recorder3.getTrace();

View file

@ -72,7 +72,7 @@ public class DebuggerCopyActionsPluginScreenShots extends GhidraScreenShotGenera
mb.createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
new TestDebuggerTargetTraceMapper(mb.testProcess1));
new TestDebuggerTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
tb = new ToyDBTraceBuilder(recorder.getTrace());
}

View file

@ -22,8 +22,7 @@ import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest.TestDebuggerTargetTraceMapper;
import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceProxyPlugin;
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.app.services.TraceRecorder;
import ghidra.app.services.*;
import ghidra.dbg.model.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.thread.TraceThread;
@ -54,8 +53,8 @@ public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator
mb.createTestModel();
TestTargetProcess process = mb.testModel.addProcess(1234);
TraceRecorder recorder =
modelService.recordTarget(process, new TestDebuggerTargetTraceMapper(process));
TraceRecorder recorder = modelService.recordTarget(process,
new TestDebuggerTargetTraceMapper(process), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
TestTargetThread mainThread = process.addThread(1);
@ -96,10 +95,10 @@ public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator
TestTargetProcess dummy1 = mb.testModel.addProcess(4321);
TestTargetProcess dummy2 = mb.testModel.addProcess(5432);
TraceRecorder recDummy1 =
modelService.recordTarget(dummy1, new TestDebuggerTargetTraceMapper(dummy1));
TraceRecorder recDummy2 =
modelService.recordTarget(dummy2, new TestDebuggerTargetTraceMapper(dummy2));
TraceRecorder recDummy1 = modelService.recordTarget(dummy1,
new TestDebuggerTargetTraceMapper(dummy1), ActionSource.AUTOMATIC);
TraceRecorder recDummy2 = modelService.recordTarget(dummy2,
new TestDebuggerTargetTraceMapper(dummy2), ActionSource.AUTOMATIC);
traceManager.setAutoCloseOnTerminate(false);

View file

@ -15,7 +15,8 @@
*/
package ghidra.app.plugin.core.debug.gui.breakpoint;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.awt.*;
import java.awt.event.MouseEvent;
@ -137,7 +138,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
createProgramFromTrace(trace);
intoProject(trace);

View file

@ -121,7 +121,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
addLiveMemoryAndBreakpoint(mb.testProcess1, recorder);
@ -145,7 +145,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
addLiveMemoryAndBreakpoint(mb.testProcess1, recorder);
@ -210,7 +210,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
createProgramFromTrace(trace);
intoProject(trace);
@ -471,7 +471,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
createTestModel();
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
createProgramFromTrace(trace);
intoProject(trace);
@ -514,11 +514,11 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
mb.createTestProcessesAndThreads();
TraceRecorder recorder1 = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace1 = recorder1.getTrace();
TraceRecorder recorder3 = modelService.recordTarget(mb.testProcess3,
createTargetTraceMapper(mb.testProcess3));
createTargetTraceMapper(mb.testProcess3), ActionSource.AUTOMATIC);
Trace trace3 = recorder3.getTrace();
createProgramFromTrace(trace1);

View file

@ -36,6 +36,7 @@ import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyIntoProgramDialog.Ra
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
import ghidra.app.services.ActionSource;
import ghidra.app.services.DebuggerStaticMappingService;
import ghidra.dbg.DebuggerModelListener;
import ghidra.dbg.target.TargetObject;
@ -456,7 +457,8 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG
mb.testModel.addModelListener(listener);
mb.createTestProcessesAndThreads();
modelService.recordTarget(mb.testProcess1, createTargetTraceMapper(mb.testProcess1));
modelService.recordTarget(mb.testProcess1, createTargetTraceMapper(mb.testProcess1),
ActionSource.AUTOMATIC);
mb.testProcess1.memory.addRegion(".text", mb.rng(0x55550000, 0x5555ffff), "rx");
mb.testProcess1.memory.setMemory(mb.addr(0x55550000), mb.arr(1, 2, 3, 4, 5, 6, 7, 8));
waitForPass(() -> {

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.plugin.core.debug.gui.register;
import static ghidra.lifecycle.Unfinished.*;
import static ghidra.lifecycle.Unfinished.TODO;
import static org.junit.Assert.*;
import java.math.BigInteger;
@ -33,6 +33,7 @@ import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec;
import ghidra.app.plugin.core.debug.gui.action.NoneLocationTrackingSpec;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
import ghidra.app.plugin.core.debug.gui.register.DebuggerRegistersProvider.RegisterTableColumns;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.async.AsyncTestUtils;
import ghidra.program.model.data.*;
@ -146,7 +147,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
Register::isBaseRegister);
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
waitFor(() -> {
TraceThread thread = recorder.getTraceThread(mb.testThread1);

View file

@ -27,6 +27,7 @@ import org.junit.*;
import generic.Unique;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.async.AsyncTestUtils;
import ghidra.dbg.model.TestTargetRegisterBankInThread;
@ -208,7 +209,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
mb.testProcess1.memory.writeMemory(mb.addr(0x00400000), tb.arr(1, 2, 3, 4));
recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
@ -348,7 +349,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
mb.testProcess1.addRegion(".text", mb.rng(0x00400000, 0x00401000), "rx");
recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));

View file

@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.dbg.model.TestTargetRegister;
import ghidra.dbg.target.*;
@ -63,8 +64,8 @@ public class LargestSubDebuggerRegisterMapperTest extends AbstractGhidraHeadedDe
protected DebuggerRegisterMapper getRegisterMapperBase() throws Throwable {
mb.testProcess1.regs.addRegistersFromLanguage(getSLEIGH_X86_64_LANGUAGE(), r -> true);
TraceRecorder recorder =
modelService.recordTarget(mb.testProcess1, new TestTargetMapper(mb.testProcess1));
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
new TestTargetMapper(mb.testProcess1), ActionSource.AUTOMATIC);
TraceThread thread1 = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
DebuggerRegisterMapper rm = waitForValue(() -> recorder.getRegisterMapper(thread1));
waitForValue(() -> rm.getTargetRegister("rax"));
@ -75,8 +76,8 @@ public class LargestSubDebuggerRegisterMapperTest extends AbstractGhidraHeadedDe
protected DebuggerRegisterMapper getRegisterMapperSub() throws Throwable {
mb.testProcess1.regs.addRegistersFromLanguage(getSLEIGH_X86_LANGUAGE(), r -> true);
TraceRecorder recorder =
modelService.recordTarget(mb.testProcess1, new TestTargetMapper(mb.testProcess1));
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
new TestTargetMapper(mb.testProcess1), ActionSource.AUTOMATIC);
TraceThread thread1 = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
DebuggerRegisterMapper rm = waitForValue(() -> recorder.getRegisterMapper(thread1));
waitForValue(() -> rm.getTargetRegister("eax"));

View file

@ -166,12 +166,12 @@ public class DebuggerLogicalBreakpointServiceTest extends AbstractGhidraHeadedDe
public void startRecorder1() throws Throwable {
recorder1 = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
}
public void startRecorder3() throws Throwable {
recorder3 = modelService.recordTarget(mb.testProcess3,
createTargetTraceMapper(mb.testProcess3));
createTargetTraceMapper(mb.testProcess3), ActionSource.AUTOMATIC);
}
@After

View file

@ -37,6 +37,7 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractConnectAction;
import ghidra.app.plugin.core.debug.service.model.DebuggerConnectDialog.FactoryEntry;
import ghidra.app.plugin.core.debug.service.model.TestDebuggerProgramLaunchOpinion.TestDebuggerProgramLaunchOffer;
import ghidra.app.plugin.core.debug.service.model.launch.DebuggerProgramLaunchOffer;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.async.AsyncPairingQueue;
import ghidra.dbg.DebuggerModelFactory;
@ -213,7 +214,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
assertEquals(Set.of(), Set.copyOf(modelService.getTraceRecorders()));
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
assertEquals(Set.of(recorder), Set.copyOf(modelService.getTraceRecorders()));
}
@ -228,7 +229,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
modelService.addTraceRecordersChangedListener(wrapper);
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
new VerificationsInOrder() {
{
@ -243,7 +244,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
// Strong ref
CollectionChangeDelegateWrapper<TraceRecorder> wrapper =
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
@ -265,7 +266,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
assertNotNull(recorder);
waitOn(recorder.init()); // Already initializing, just wait for it to complete
@ -300,7 +301,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
assertEquals(recorder, modelService.getRecorder(mb.testProcess1));
}
@ -311,7 +312,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
assertEquals(recorder, modelService.getRecorder(recorder.getTrace()));
}
@ -322,7 +323,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
assertEquals(mb.testProcess1, modelService.getTarget(recorder.getTrace()));
}
@ -333,7 +334,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
assertEquals(recorder.getTrace(), modelService.getTrace(mb.testProcess1));
}
@ -344,7 +345,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
// The most complicated case, lest I want another dimension in a cross product
mb.createTestThreadStacksAndFramesHaveRegisterBanks();
@ -372,8 +373,8 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
preRec.run();
modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
modelService.recordTarget(mb.testProcess1, createTargetTraceMapper(mb.testProcess1),
ActionSource.AUTOMATIC);
postRec.run();
@ -419,8 +420,8 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
createTestModel();
mb.createTestProcessesAndThreads();
modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
modelService.recordTarget(mb.testProcess1, createTargetTraceMapper(mb.testProcess1),
ActionSource.AUTOMATIC);
// The most complicated case, lest I want another dimension in a cross product
mb.createTestThreadStacksAndFramesHaveRegisterBanks();
@ -439,9 +440,9 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
// NOTE: getTargetFocus assumes the target is being recorded
modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
modelService.recordTarget(mb.testProcess3,
createTargetTraceMapper(mb.testProcess3));
createTargetTraceMapper(mb.testProcess3), ActionSource.AUTOMATIC);
assertNull(modelService.getTargetFocus(mb.testProcess1));
assertNull(modelService.getTargetFocus(mb.testProcess3));

View file

@ -26,6 +26,7 @@ import com.google.common.collect.Range;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.mapping.DebuggerRegisterMapper;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.dbg.model.TestTargetMemoryRegion;
import ghidra.dbg.model.TestTargetRegisterBankInThread;
@ -48,7 +49,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
waitForPass(() -> {
assertNotNull(recorder.getTraceThread(mb.testThread1));
assertNotNull(recorder.getTraceThread(mb.testThread2));
@ -61,7 +62,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
TestTargetMemoryRegion targetRegion =
@ -97,7 +98,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
Language lang = trace.getBaseLanguage();
Register r0 = lang.getRegister("r0");
@ -131,7 +132,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
Language lang = trace.getBaseLanguage();
Register pc = lang.getRegister("pc");
@ -180,7 +181,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
Language lang = trace.getBaseLanguage();
Register pc = lang.getRegister("pc");
@ -229,7 +230,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
Language lang = trace.getBaseLanguage();
Register pc = lang.getRegister("pc");

View file

@ -26,6 +26,7 @@ import org.junit.experimental.categories.Category;
import generic.test.category.NightlyCategory;
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.dbg.model.TestTargetStack;
import ghidra.dbg.model.TestTargetStackFrameHasRegisterBank;
@ -296,7 +297,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
traceManager.openTrace(trace);
@ -337,7 +338,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
waitForValue(() -> modelService.getTarget(trace));
@ -399,7 +400,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
mb.createTestProcessesAndThreads();
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
traceManager.openTrace(trace);

View file

@ -26,6 +26,7 @@ import org.junit.Test;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.mapping.DebuggerRegisterMapper;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.services.ActionSource;
import ghidra.app.services.TraceRecorder;
import ghidra.dbg.model.TestTargetRegisterBankInThread;
import ghidra.dbg.testutil.DebuggerModelTestUtils;
@ -50,7 +51,7 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge
"r1", new byte[] { 6 })));
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
Trace trace = recorder.getTrace();
@ -93,7 +94,7 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge
"r1", new byte[] { 6 })));
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
createTargetTraceMapper(mb.testProcess1));
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
Trace trace = recorder.getTrace();