GP-3857: Port most Debugger components to TraceRmi.

This commit is contained in:
Dan 2023-11-02 10:43:31 -04:00
parent 7e4d2bcfaa
commit fd4380c07a
222 changed files with 7241 additions and 3752 deletions

View file

@ -0,0 +1,185 @@
/* ###
* 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.plugin.core.debug.gui.breakpoint;
import java.awt.event.MouseEvent;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import db.Transaction;
import generic.Unique;
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest.TestDebuggerTargetTraceMapper;
import ghidra.app.plugin.core.debug.service.breakpoint.DebuggerLogicalBreakpointServicePlugin;
import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceProxyPlugin;
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
import ghidra.app.plugin.core.decompile.DecompilePlugin;
import ghidra.app.plugin.core.decompile.DecompilerProvider;
import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin;
import ghidra.app.services.*;
import ghidra.app.util.viewer.listingpanel.ListingPanel;
import ghidra.dbg.model.TestDebuggerModelBuilder;
import ghidra.debug.api.action.ActionSource;
import ghidra.debug.api.breakpoint.LogicalBreakpoint;
import ghidra.debug.api.breakpoint.LogicalBreakpoint.State;
import ghidra.debug.api.model.TraceRecorder;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.util.Msg;
import ghidra.util.Swing;
import ghidra.util.task.TaskMonitor;
import help.screenshot.GhidraScreenShotGenerator;
public class DebuggerBreakpointMarkerPluginScreenShots extends GhidraScreenShotGenerator {
private DebuggerModelService modelService;
private DebuggerTraceManagerService traceManager;
private DebuggerStaticMappingService mappingService;
private DebuggerLogicalBreakpointService breakpointService;
private DebuggerBreakpointMarkerPlugin breakpointMarkerPlugin;
private ProgramManager programManager;
private TestDebuggerModelBuilder mb;
private CodeViewerProvider listing;
protected static Address addr(Program program, long offset) {
return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
}
@Before
public void setUpMine() throws Exception {
modelService = addPlugin(tool, DebuggerModelServiceProxyPlugin.class);
traceManager = addPlugin(tool, DebuggerTraceManagerServicePlugin.class);
mappingService = addPlugin(tool, DebuggerStaticMappingServicePlugin.class);
breakpointService = addPlugin(tool, DebuggerLogicalBreakpointServicePlugin.class);
breakpointMarkerPlugin = addPlugin(tool, DebuggerBreakpointMarkerPlugin.class);
programManager = addPlugin(tool, ProgramManagerPlugin.class);
listing = waitForComponentProvider(CodeViewerProvider.class);
program = programManager.getCurrentProgram();
mb = new TestDebuggerModelBuilder();
}
@Test
public void testCaptureDebuggerBreakpointMarkerPlugin() throws Throwable {
ListingPanel panel = listing.getListingPanel();
mb.createTestModel();
modelService.addModel(mb.testModel);
mb.createTestProcessesAndThreads();
TestDebuggerTargetTraceMapper mapper = new TestDebuggerTargetTraceMapper(mb.testProcess1);
TraceRecorder recorder =
modelService.recordTarget(mb.testProcess1, mapper, ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
traceManager.openTrace(trace);
traceManager.activateTrace(trace);
tool.getProject()
.getProjectData()
.getRootFolder()
.createFile("WinHelloCPP", program, TaskMonitor.DUMMY);
try (Transaction tx = trace.openTransaction("Add Mapping")) {
mappingService.addIdentityMapping(trace, program, Lifespan.nowOn(0), true);
}
waitForValue(() -> mappingService.getOpenMappedLocation(
new DefaultTraceLocation(trace, null, Lifespan.at(0), mb.addr(0x00401c60))));
Msg.debug(this, "Placing breakpoint");
breakpointService.placeBreakpointAt(program, addr(program, 0x00401c60), 1,
Set.of(TraceBreakpointKind.SW_EXECUTE), "");
Msg.debug(this, "Disabling breakpoint");
LogicalBreakpoint lb = waitForValue(() -> Unique.assertAtMostOne(
breakpointService.getBreakpointsAt(program, addr(program, 0x00401c60))));
lb.disable();
waitForCondition(() -> lb.computeState() == State.DISABLED);
Msg.debug(this, "Placing another");
breakpointService.placeBreakpointAt(program, addr(program, 0x00401c63), 1,
Set.of(TraceBreakpointKind.SW_EXECUTE), "");
Msg.debug(this, "Saving program");
program.save("Placed breakpoints", TaskMonitor.DUMMY);
Msg.debug(this, "Clicking and capturing");
AbstractDebuggerBreakpointMarkerPluginTest.clickListing(panel, addr(program, 0x00401c66),
MouseEvent.BUTTON3);
waitForSwing();
captureProviderWithScreenShot(listing);
}
@Test
public void testCaptureDebuggerDecompilerBreakpointMargin() throws Throwable {
mb.createTestModel();
modelService.addModel(mb.testModel);
mb.createTestProcessesAndThreads();
TestDebuggerTargetTraceMapper mapper = new TestDebuggerTargetTraceMapper(mb.testProcess1);
TraceRecorder recorder =
modelService.recordTarget(mb.testProcess1, mapper, ActionSource.AUTOMATIC);
Trace trace = recorder.getTrace();
traceManager.openTrace(trace);
traceManager.activateTrace(trace);
tool.getProject()
.getProjectData()
.getRootFolder()
.createFile("WinHelloCPP", program, TaskMonitor.DUMMY);
try (Transaction tx = trace.openTransaction("Add Mapping")) {
mappingService.addIdentityMapping(trace, program, Lifespan.nowOn(0), true);
}
waitForValue(() -> mappingService.getOpenMappedLocation(
new DefaultTraceLocation(trace, null, Lifespan.at(0), mb.addr(0x00401070))));
Msg.debug(this, "Placing breakpoint");
breakpointService.placeBreakpointAt(program, addr(program, 0x00401070), 1,
Set.of(TraceBreakpointKind.SW_EXECUTE), "");
addPlugin(tool, DecompilePlugin.class);
DecompilerProvider decompilerProvider = waitForComponentProvider(DecompilerProvider.class);
Swing.runNow(() -> tool.showComponentProvider(decompilerProvider, true));
goTo(tool, program, addr(program, 0x00401070));
waitForCondition(() -> decompilerProvider.getDecompilerPanel().getLines().size() > 4);
captureIsolatedProvider(decompilerProvider, 500, 700);
}
@Test
public void testCaptureDebuggerPlaceBreakpointDialog() throws Throwable {
runSwing(
() -> listing.goTo(program, new ProgramLocation(program, addr(program, 0x00401c63))));
performAction(breakpointMarkerPlugin.actionSetSoftwareBreakpoint, false);
DebuggerPlaceBreakpointDialog dialog =
waitForDialogComponent(DebuggerPlaceBreakpointDialog.class);
dialog.setName("After setup");
captureDialog(dialog);
}
}

View file

@ -0,0 +1,189 @@
/* ###
* 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.plugin.core.debug.gui.breakpoint;
import static ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest.*;
import static org.junit.Assert.*;
import java.util.Set;
import org.junit.*;
import db.Transaction;
import generic.Unique;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest.TestDebuggerTargetTraceMapper;
import ghidra.app.plugin.core.debug.service.breakpoint.DebuggerLogicalBreakpointServicePlugin;
import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceProxyPlugin;
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin;
import ghidra.app.services.*;
import ghidra.dbg.model.TestDebuggerModelBuilder;
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
import ghidra.dbg.target.TargetBreakpointSpecContainer;
import ghidra.dbg.target.TargetTogglable;
import ghidra.dbg.testutil.DebuggerModelTestUtils;
import ghidra.debug.api.action.ActionSource;
import ghidra.debug.api.breakpoint.LogicalBreakpoint;
import ghidra.debug.api.model.TraceRecorder;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.test.ToyProgramBuilder;
import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
import help.screenshot.GhidraScreenShotGenerator;
public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenerator
implements DebuggerModelTestUtils {
TestDebuggerModelBuilder mb = new TestDebuggerModelBuilder();
DebuggerModelServiceProxyPlugin modelService;
DebuggerStaticMappingService mappingService;
DebuggerLogicalBreakpointService breakpointService;
DebuggerTraceManagerService traceManager;
ProgramManager programManager;
Program program;
protected static Address addr(Trace trace, long offset) {
return trace.getBaseAddressFactory().getDefaultAddressSpace().getAddress(offset);
}
protected static Address addr(Program program, long offset) {
return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
}
@Before
public void setUpMine() throws Exception {
breakpointService = addPlugin(tool, DebuggerLogicalBreakpointServicePlugin.class);
modelService = addPlugin(tool, DebuggerModelServiceProxyPlugin.class);
mappingService = addPlugin(tool, DebuggerStaticMappingServicePlugin.class);
traceManager = addPlugin(tool, DebuggerTraceManagerServicePlugin.class);
programManager = addPlugin(tool, ProgramManagerPlugin.class);
program = createDefaultProgram("echo", ToyProgramBuilder._X64, this);
waitForProgram(program);
tool.getProject()
.getProjectData()
.getRootFolder()
.createFile("echo", program, TaskMonitor.DUMMY);
}
@After
public void tearDownMine() {
Msg.debug(this, "Tearing down");
Msg.debug(this, "Service breakpoints:");
for (LogicalBreakpoint lb : breakpointService.getAllBreakpoints()) {
Msg.debug(this, " bp: " + lb);
}
DebuggerBreakpointsProvider provider =
waitForComponentProvider(DebuggerBreakpointsProvider.class);
Msg.debug(this, "Provider breakpoints:");
for (LogicalBreakpointRow row : provider.breakpointTableModel.getModelData()) {
Msg.debug(this, " bp: " + row.getLogicalBreakpoint());
}
if (program != null) {
program.release(this);
}
}
@Test
public void testCaptureDebuggerBreakpointsPlugin() throws Throwable {
addPlugin(tool, DebuggerBreakpointsPlugin.class);
DebuggerBreakpointsProvider provider =
waitForComponentProvider(DebuggerBreakpointsProvider.class);
mb.createTestModel();
modelService.addModel(mb.testModel);
mb.createTestProcessesAndThreads();
TraceRecorder recorder1 = modelService.recordTarget(mb.testProcess1,
new TestDebuggerTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
TraceRecorder recorder3 = modelService.recordTarget(mb.testProcess3,
new TestDebuggerTargetTraceMapper(mb.testProcess3), ActionSource.AUTOMATIC);
Trace trace1 = recorder1.getTrace();
Trace trace3 = recorder3.getTrace();
programManager.openProgram(program);
traceManager.openTrace(trace1);
traceManager.openTrace(trace3);
mb.testProcess1.addRegion("echo:.text", mb.rng(0x00400000, 0x00400fff), "rx");
mb.testProcess1.addRegion("echo:.data", mb.rng(0x00600000, 0x00600fff), "rw");
mb.testProcess3.addRegion("echo:.text", mb.rng(0x7fac0000, 0x7fac0fff), "rx");
try (Transaction tx = trace1.openTransaction("Add mapping")) {
DebuggerStaticMappingUtils.addMapping(
new DefaultTraceLocation(trace1, null, Lifespan.nowOn(0), addr(trace1, 0x00400000)),
new ProgramLocation(program, addr(program, 0x00400000)), 0x00210000, false);
}
try (Transaction tx = trace3.openTransaction("Add mapping")) {
DebuggerStaticMappingUtils.addMapping(
new DefaultTraceLocation(trace3, null, Lifespan.nowOn(0), addr(trace3, 0x7fac0000)),
new ProgramLocation(program, addr(program, 0x00400000)), 0x00010000, false);
}
waitForSwing();
try (Transaction tx = program.openTransaction("Add breakpoint")) {
program.getBookmarkManager()
.setBookmark(addr(program, 0x00401234), LogicalBreakpoint.ENABLED_BOOKMARK_TYPE,
"SW_EXECUTE;1", "before connect");
program.getBookmarkManager()
.setBookmark(addr(program, 0x00604321), LogicalBreakpoint.ENABLED_BOOKMARK_TYPE,
"WRITE;4", "write version");
}
TargetBreakpointSpecContainer bc1 =
waitFor(() -> Unique.assertAtMostOne(recorder1.collectBreakpointContainers(null)),
"No container");
waitOn(bc1.placeBreakpoint(mb.addr(0x00401234), Set.of(TargetBreakpointKind.SW_EXECUTE)));
waitOn(bc1.placeBreakpoint(mb.rng(0x00604321, 0x00604324),
Set.of(TargetBreakpointKind.WRITE)));
TargetBreakpointSpecContainer bc3 =
waitFor(() -> Unique.assertAtMostOne(recorder3.collectBreakpointContainers(null)),
"No container");
waitOn(bc3.placeBreakpoint(mb.addr(0x7fac1234), Set.of(TargetBreakpointKind.SW_EXECUTE)));
TargetTogglable bp3 = (TargetTogglable) waitForValue(
() -> Unique.assertAtMostOne(bc3.getCachedElements().values()));
waitOn(bp3.disable());
TraceBreakpoint bpt = waitForValue(() -> Unique.assertAtMostOne(
trace3.getBreakpointManager()
.getBreakpointsAt(recorder3.getSnap(), addr(trace3, 0x7fac1234))));
waitForPass(() -> {
Set<LogicalBreakpoint> allBreakpoints = breakpointService.getAllBreakpoints();
assertEquals(2, allBreakpoints.size());
});
waitForPass(() -> {
assertFalse(bpt.isEnabled(0));
});
/**
* TODO: Might be necessary to debounce and wait for service callbacks to settle. Sometimes,
* there are 3 for just a moment, and then additional callbacks mess things up.
*/
waitForPass(() -> {
assertEquals(2, provider.breakpointTable.getRowCount());
assertEquals(3, provider.locationTable.getRowCount());
});
captureIsolatedProvider(provider, 600, 600);
}
}

View file

@ -0,0 +1,71 @@
/* ###
* 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 ghidraclass.debugger.screenshot;
import java.io.File;
import org.junit.*;
import db.Transaction;
import ghidra.app.util.importer.AutoImporter;
import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.LoadResults;
import ghidra.base.project.GhidraProject;
import ghidra.framework.Application;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.TestEnv;
import ghidra.util.task.ConsoleTaskMonitor;
import ghidra.util.task.TaskMonitor;
public class TutorialDebuggerMaintenance extends AbstractGhidraHeadedIntegrationTest {
public static final TaskMonitor CONSOLE = new ConsoleTaskMonitor();
public PluginTool tool;
public TestEnv env;
public Program program;
@Before
public void setUp() throws Throwable {
env = new TestEnv();
tool = env.launchDefaultTool();
}
@After
public void tearDown() throws Throwable {
if (program != null) {
program.release(this);
program = null;
}
}
@Test
public void testRecreateTermminesGzf() throws Throwable {
File termmines = Application.getModuleDataFile("TestResources", "termmines").getFile(false);
LoadResults<Program> results = AutoImporter.importByUsingBestGuess(termmines,
env.getProject(), "/", this, new MessageLog(), CONSOLE);
program = results.getPrimaryDomainObject();
try (Transaction tx = program.openTransaction("Analyze")) {
program.setExecutablePath("/tmp/termmines");
GhidraProject.analyze(program);
}
File dest = new File(termmines.getParentFile(), "termmines.gzf");
dest.delete();
program.saveToPackedFile(dest, CONSOLE);
}
}

View file

@ -0,0 +1,819 @@
/* ###
* 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 ghidraclass.debugger.screenshot;
import static org.junit.Assert.assertTrue;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.io.*;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import db.Transaction;
import docking.action.DockingActionIf;
import docking.widgets.fieldpanel.FieldPanel;
import generic.Unique;
import generic.jar.ResourceFile;
import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.context.ProgramLocationActionContext;
import ghidra.app.decompiler.component.DecompilerPanel;
import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.analysis.AutoAnalysisPlugin;
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
import ghidra.app.plugin.core.debug.gui.action.*;
import ghidra.app.plugin.core.debug.gui.breakpoint.DebuggerBreakpointsProvider;
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsoleProvider;
import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyActionsPlugin;
import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyIntoProgramDialog;
import ghidra.app.plugin.core.debug.gui.diff.DebuggerTraceViewDiffPlugin;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
import ghidra.app.plugin.core.debug.gui.memory.DebuggerMemoryBytesProvider;
import ghidra.app.plugin.core.debug.gui.memory.DebuggerRegionsProvider;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProvider;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerStaticMappingProvider;
import ghidra.app.plugin.core.debug.gui.pcode.DebuggerPcodeStepperPlugin;
import ghidra.app.plugin.core.debug.gui.pcode.DebuggerPcodeStepperProvider;
import ghidra.app.plugin.core.debug.gui.register.DebuggerRegistersProvider;
import ghidra.app.plugin.core.debug.gui.stack.DebuggerStackProvider;
import ghidra.app.plugin.core.debug.gui.stack.vars.VariableValueHoverPlugin;
import ghidra.app.plugin.core.debug.gui.target.DebuggerTargetsPlugin;
import ghidra.app.plugin.core.debug.gui.thread.DebuggerThreadsProvider;
import ghidra.app.plugin.core.debug.gui.time.DebuggerTimeProvider;
import ghidra.app.plugin.core.debug.gui.time.DebuggerTimeSelectionDialog;
import ghidra.app.plugin.core.debug.gui.watch.DebuggerWatchesProvider;
import ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin;
import ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePlugin.EmulateProgramAction;
import ghidra.app.plugin.core.debug.service.model.DebuggerConnectDialog;
import ghidra.app.plugin.core.debug.stack.StackUnwinderTest;
import ghidra.app.plugin.core.debug.stack.StackUnwinderTest.HoverLocation;
import ghidra.app.plugin.core.debug.stack.UnwindStackCommand;
import ghidra.app.plugin.core.decompile.DecompilerProvider;
import ghidra.app.script.GhidraState;
import ghidra.app.services.*;
import ghidra.app.services.DebuggerEmulationService.EmulationResult;
import ghidra.app.util.importer.AutoImporter;
import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.LoadResults;
import ghidra.async.AsyncTestUtils;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.target.TargetLauncher;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.testutil.DummyProc;
import ghidra.dbg.util.ConfigurableFactory.Property;
import ghidra.debug.api.model.DebuggerProgramLaunchOffer;
import ghidra.debug.api.model.DebuggerProgramLaunchOffer.*;
import ghidra.debug.api.watch.WatchRow;
import ghidra.debug.flatapi.FlatDebuggerAPI;
import ghidra.framework.Application;
import ghidra.framework.TestApplicationUtils;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.model.DomainObject;
import ghidra.framework.plugintool.util.PluginUtils;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.util.GhidraProgramUtilities;
import ghidra.program.util.ProgramSelection;
import ghidra.test.TestEnv;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.modules.TraceModule;
import ghidra.trace.model.modules.TraceSection;
import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.time.schedule.*;
import ghidra.util.InvalidNameException;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.ConsoleTaskMonitor;
import help.screenshot.GhidraScreenShotGenerator;
public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
implements AsyncTestUtils {
protected static final String TUTORIAL_PATH =
TestApplicationUtils.getInstallationDirectory() + "/GhidraDocs/GhidraClass/Debugger/";
protected static final File TUTORIAL_DIR = new File(TUTORIAL_PATH);
protected static final String TERMMINES_PATH = "/tmp/termmines";
protected final ConsoleTaskMonitor monitor = new ConsoleTaskMonitor();
protected ProgramManager programManager;
protected CodeViewerService staticListingService;
protected DebuggerModelService modelService;
protected DebuggerModelFactory gdbFactory;
protected final FlatDebuggerAPI flatDbg = new FlatDebuggerAPI() {
@Override
public GhidraState getState() {
Navigatable nav = staticListingService.getNavigatable();
return new GhidraState(tool, env.getProject(),
nav.getProgram(), nav.getLocation(), nav.getSelection(), nav.getHighlight());
}
};
@Override
protected TestEnv newTestEnv() throws Exception {
return new TestEnv("DebuggerCourse");
}
// TODO: Propose this replace waitForProgram
public static void waitForDomainObject(DomainObject object) {
object.flushEvents();
waitForSwing();
}
protected void intoProject(DomainObject obj) {
waitForDomainObject(obj);
DomainFolder rootFolder = tool.getProject()
.getProjectData()
.getRootFolder();
waitForCondition(() -> {
try {
rootFolder.createFile(obj.getName(), obj, monitor);
return true;
}
catch (InvalidNameException | CancelledException e) {
throw new AssertionError(e);
}
catch (IOException e) {
// Usually "object is busy". Try again.
return false;
}
});
}
@Override
public void prepareTool() {
tool = env.launchTool("Debugger");
}
@Override
public void loadProgram() throws Exception {
loadProgram("termmines");
try (Transaction tx = program.openTransaction("Set exe path")) {
program.setExecutablePath(TERMMINES_PATH);
}
intoProject(program);
}
@Override
public void saveOrDisplayImage(String name) {
if (TUTORIAL_DIR.exists()) {
TUTORIAL_DIR.mkdirs();
}
name = name.substring("test".length());
finished(TUTORIAL_DIR, name + ".png");
}
protected CodeViewerService getStaticListingService() {
for (CodeViewerService viewer : tool.getServices(CodeViewerService.class)) {
if (viewer instanceof DebuggerListingService) {
continue;
}
return viewer;
}
return null;
}
@Before
public void setUpDebugger() throws Throwable {
ResourceFile termminesRsrc = Application.getModuleDataFile("TestResources", "termmines");
File termmines = new File(TERMMINES_PATH);
try {
Files.copy(termminesRsrc.getFile(false).toPath(), termmines.toPath());
}
catch (FileNotFoundException e) {
Msg.warn(this, "Could not update " + TERMMINES_PATH);
}
catch (FileAlreadyExistsException e) {
Files.delete(termmines.toPath());
Files.copy(termminesRsrc.getFile(false).toPath(), termmines.toPath());
}
termmines.setExecutable(true);
programManager = tool.getService(ProgramManager.class);
staticListingService = getStaticListingService();
modelService = tool.getService(DebuggerModelService.class);
gdbFactory = modelService.getModelFactories()
.stream()
.filter(f -> "gdb".equals(f.getBrief()))
.findAny()
.get();
@SuppressWarnings("unchecked")
Property<String> gdbPathProp =
(Property<String>) gdbFactory.getOptions().get("GDB launch command");
gdbPathProp.setValue(DummyProc.which("gdb"));
}
@Test
public void testGettingStarted_ToolWSpecimen() {
captureToolWindow(1920, 1080);
}
protected void launchProgramInGdb(String extraArgs) throws Throwable {
DebuggerProgramLaunchOffer offer = modelService.getProgramLaunchOffers(program)
.filter(o -> "IN-VM GDB".equals(o.getConfigName()))
.findFirst()
.get();
LaunchConfigurator config = new LaunchConfigurator() {
@Override
public Map<String, ?> configureLauncher(TargetLauncher launcher,
Map<String, ?> arguments, RelPrompt relPrompt) {
if (extraArgs.length() == 0) {
return arguments;
}
Map<String, Object> adjusted = new HashMap<>(arguments);
TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS.adjust(adjusted,
c -> c + " " + extraArgs);
return adjusted;
}
};
LaunchResult result = waitOn(offer.launchProgram(monitor, PromptMode.NEVER, config));
if (result.exception() != null) {
throw result.exception();
}
}
protected void launchProgramInGdb() throws Throwable {
launchProgramInGdb("");
}
@Test
public void testGettingStarted_DisassemblyAfterLaunch() throws Throwable {
launchProgramInGdb();
captureToolWindow(1920, 1080);
}
@Test
public void testBreakpoints_EmptyAfterLaunch() throws Throwable {
launchProgramInGdb();
tool.setSize(1920, 1080);
captureProvider(DebuggerBreakpointsProvider.class);
}
protected void placeBreakpointsSRandRand() throws Throwable {
assertTrue(flatDbg.execute("break srand"));
assertTrue(flatDbg.execute("break rand"));
waitForCondition(() -> flatDbg.getAllBreakpoints().size() == 2);
}
protected void placeBreakpointsRand() throws Throwable {
assertTrue(flatDbg.execute("break rand"));
waitForCondition(() -> flatDbg.getAllBreakpoints().size() == 1);
}
@Test
public void testBreakpoints_PopAfterSRandRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsSRandRand();
tool.setSize(1920, 1080);
captureProvider(DebuggerBreakpointsProvider.class);
}
protected Address navigateToBreakpoint(String comment) {
TraceBreakpoint bp = flatDbg.getAllBreakpoints()
.stream()
.flatMap(l -> l.getTraceBreakpoints().stream())
.filter(l -> comment.equals(l.getComment()))
.findAny()
.get();
Address dynAddr = bp.getMinAddress();
flatDbg.goToDynamic(dynAddr);
return dynAddr;
}
@Test
public void testBreakpoints_MissingModuleNote() throws Throwable {
launchProgramInGdb();
placeBreakpointsSRandRand();
navigateToBreakpoint("srand");
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerConsoleProvider.class);
}
protected Program importModule(TraceModule module) throws Throwable {
Program prog = null;
try {
MessageLog log = new MessageLog();
LoadResults<Program> result = AutoImporter.importByUsingBestGuess(
new File(module.getName()), env.getProject(), "/", this, log, monitor);
result.save(env.getProject(), this, log, monitor);
prog = result.getPrimaryDomainObject();
GhidraProgramUtilities.markProgramNotToAskToAnalyze(prog);
programManager.openProgram(prog);
}
finally {
if (prog != null) {
prog.release(this);
}
}
return prog;
}
protected void analyze(Program prog) {
DockingActionIf actAutoAnalyze = Unique.assertOne(getActionsByOwnerAndName(tool,
PluginUtils.getPluginNameFromClass(AutoAnalysisPlugin.class), "Auto Analyze"));
performAction(actAutoAnalyze);
}
protected TraceModule getModuleContaining(Address dynAddr) {
return Unique.assertOne(flatDbg.getCurrentTrace()
.getModuleManager()
.getModulesAt(flatDbg.getCurrentSnap(), dynAddr));
}
protected void disassembleSymbol(Program prog, String name) {
for (Symbol sym : prog.getSymbolTable().getLabelOrFunctionSymbols(name, null)) {
tool.executeBackgroundCommand(new DisassembleCommand(sym.getAddress(), null, true),
prog);
}
waitForTasks(600 * 1000);
}
@Test
public void testBreakpoints_SyncedAfterImportLibC() throws Throwable {
launchProgramInGdb();
placeBreakpointsSRandRand();
showProvider(DebuggerBreakpointsProvider.class);
Address dynAddr = navigateToBreakpoint("srand");
TraceModule modLibC = getModuleContaining(dynAddr);
Program progLibC = importModule(modLibC);
waitForCondition(() -> flatDbg.translateDynamicToStatic(dynAddr) != null);
disassembleSymbol(progLibC, "srand");
// Just to be sure.
goTo(tool, progLibC, flatDbg.translateDynamicToStatic(dynAddr));
captureToolWindow(1920, 1080);
}
@Test
public void testBreakpoints_SeedValueAfterBreakSRand() throws Throwable {
addPlugin(tool, VariableValueHoverPlugin.class);
launchProgramInGdb();
placeBreakpointsSRandRand();
showProvider(DecompilerProvider.class);
Address dynAddr = navigateToBreakpoint("srand");
TraceModule modLibC = getModuleContaining(dynAddr);
Program progLibC = importModule(modLibC);
waitForCondition(() -> flatDbg.translateDynamicToStatic(dynAddr) != null);
disassembleSymbol(progLibC, "srand");
Address stAddr = flatDbg.translateDynamicToStatic(dynAddr);
// Just to be sure.
goTo(tool, progLibC, stAddr);
flatDbg.resume();
Function funSRand = progLibC.getFunctionManager().getFunctionAt(stAddr);
runSwing(() -> tool.setSize(1920, 1080));
DecompilerProvider dProvider = waitForComponentProvider(DecompilerProvider.class);
DecompilerPanel dPanel = dProvider.getDecompilerPanel();
HoverLocation loc = StackUnwinderTest.findTokenLocation(dPanel, funSRand, "param_1",
"void srand(ulong param_1)");
runSwing(() -> dPanel.goToToken(loc.token()));
FieldPanel fieldPanel = dPanel.getFieldPanel();
Rectangle rect = fieldPanel.getCursorBounds();
MouseEvent event =
new MouseEvent(fieldPanel, 0, System.currentTimeMillis(), 0, rect.x, rect.y, 0, false);
fieldPanel.getHoverHandler().mouseHovered(event);
waitForSwing();
sleep(500); // Give time for GDB to respond async
captureProviderWithScreenShot(dProvider);
}
@Test
public void testState_ListingAfterCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsRand();
flatDbg.resume();
flatDbg.stepOut();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerListingProvider.class);
}
@Test
public void testState_ListingStackAfterCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsRand();
flatDbg.resume();
flatDbg.stepOut();
DebuggerListingService listingService = tool.getService(DebuggerListingService.class);
listingService.setTrackingSpec(SPLocationTrackingSpec.INSTANCE);
sleep(1000);
tool.execute(new UnwindStackCommand(tool, flatDbg.getCurrentDebuggerCoordinates()),
flatDbg.getCurrentTrace());
waitForTasks();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerListingProvider.class);
}
@Test
public void testState_BytesStackAfterCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsRand();
flatDbg.resume();
flatDbg.stepOut();
DebuggerMemoryBytesProvider bytesProvider = showProvider(DebuggerMemoryBytesProvider.class);
bytesProvider.setTrackingSpec(SPLocationTrackingSpec.INSTANCE);
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerMemoryBytesProvider.class);
}
@Test
public void testState_RegistersAfterCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsRand();
flatDbg.resume();
flatDbg.stepOut();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerRegistersProvider.class);
}
@Test
public void testState_WatchesInCallSRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsSRandRand();
flatDbg.resume();
DebuggerWatchesService watchesService = tool.getService(DebuggerWatchesService.class);
watchesService.addWatch("RDI");
WatchRow watchRetPtr = watchesService.addWatch("*:8 RSP");
watchRetPtr.setDataType(
new PointerTypedefBuilder(VoidDataType.dataType, 8, null).addressSpace("ram").build());
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerWatchesProvider.class);
}
@Test
public void testNavigation_ThreadsInCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsRand();
flatDbg.resume();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerThreadsProvider.class);
}
@Test
public void testNavigation_StackInCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsRand();
Address dynAddr = navigateToBreakpoint("rand");
TraceModule modLibC = getModuleContaining(dynAddr);
importModule(modLibC);
waitForCondition(() -> flatDbg.translateDynamicToStatic(dynAddr) != null);
flatDbg.resume();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerStackProvider.class);
}
@Test
public void testNavigation_TimeAfterCallSRandCallRand() throws Throwable {
launchProgramInGdb();
placeBreakpointsSRandRand();
flatDbg.resume(); // srand
flatDbg.resume(); // rand.1
flatDbg.stepOut();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerTimeProvider.class);
}
@Test
public void testNavigation_DialogCompareTimes() throws Throwable {
launchProgramInGdb(); // main
placeBreakpointsRand();
Address pc = flatDbg.getProgramCounter();
long snapA = flatDbg.getCurrentSnap();
TraceModule modTermmines = Unique.assertOne(flatDbg.getCurrentTrace()
.getModuleManager()
.getModulesAt(snapA, pc));
TraceSection secTermminesData = modTermmines.getSectionByName(".data");
flatDbg.readMemory(secTermminesData.getStart(),
(int) secTermminesData.getRange().getLength(), monitor);
flatDbg.resume(); // rand.1
flatDbg.readMemory(secTermminesData.getStart(),
(int) secTermminesData.getRange().getLength(), monitor);
performAction("Compare",
PluginUtils.getPluginNameFromClass(DebuggerTraceViewDiffPlugin.class), false);
DebuggerTimeSelectionDialog timeDialog =
waitForDialogComponent(DebuggerTimeSelectionDialog.class);
timeDialog.setScheduleText(TraceSchedule.snap(snapA).toString());
captureDialog(timeDialog);
}
@Test
public void testNavigation_CompareTimes() throws Throwable {
launchProgramInGdb("-M 15"); // main
placeBreakpointsRand();
Address pc = flatDbg.getProgramCounter();
long snapA = flatDbg.getCurrentSnap();
TraceModule modTermmines = Unique.assertOne(flatDbg.getCurrentTrace()
.getModuleManager()
.getModulesAt(snapA, pc));
TraceSection secTermminesData = modTermmines.getSectionByName(".data");
flatDbg.readMemory(secTermminesData.getStart(),
(int) secTermminesData.getRange().getLength(), monitor);
flatDbg.resume(); // rand.1
flatDbg.waitForBreak(1000, TimeUnit.MILLISECONDS);
flatDbg.readMemory(secTermminesData.getStart(),
(int) secTermminesData.getRange().getLength(), monitor);
performAction("Compare",
PluginUtils.getPluginNameFromClass(DebuggerTraceViewDiffPlugin.class), false);
DebuggerTimeSelectionDialog timeDialog =
waitForDialogComponent(DebuggerTimeSelectionDialog.class);
runSwing(() -> timeDialog.setScheduleText(TraceSchedule.snap(snapA).toString()));
runSwing(() -> timeDialog.okCallback());
DockingActionIf actionNextDiff = waitForValue(() -> {
try {
return Unique.assertOne(getActionsByOwnerAndName(tool,
PluginUtils.getPluginNameFromClass(DebuggerTraceViewDiffPlugin.class),
"Next Difference"));
}
catch (Throwable e) {
return null;
}
});
waitForCondition(() -> actionNextDiff.isEnabled());
flatDbg.goToDynamic(secTermminesData.getStart());
performAction(actionNextDiff);
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerListingProvider.class);
}
@Test
public void testMemoryMap_RegionsAfterLaunch() throws Throwable {
launchProgramInGdb();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerRegionsProvider.class);
}
@Test
public void testMemoryMap_ModulesAfterLaunch() throws Throwable {
launchProgramInGdb();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerModulesProvider.class);
}
@Test
public void testMemoryMap_StaticMappingAfterLaunch() throws Throwable {
launchProgramInGdb();
placeBreakpointsSRandRand();
showProvider(DebuggerStaticMappingProvider.class);
Address dynAddr = navigateToBreakpoint("srand");
TraceModule modLibC = getModuleContaining(dynAddr);
importModule(modLibC);
waitForCondition(() -> flatDbg.translateDynamicToStatic(dynAddr) != null);
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerStaticMappingProvider.class);
}
@Test
public void testMemoryMap_CopyNcursesInto() throws Throwable {
launchProgramInGdb();
TraceModule modNcurses = flatDbg.getCurrentTrace()
.getModuleManager()
.getAllModules()
.stream()
.filter(m -> m.getName().contains("ncurses"))
.findAny()
.get();
DebuggerListingService listings = tool.getService(DebuggerListingService.class);
runSwing(() -> listings
.setCurrentSelection(new ProgramSelection(new AddressSet(modNcurses.getRange()))));
performAction("Copy Into New Program",
PluginUtils.getPluginNameFromClass(DebuggerCopyActionsPlugin.class), false);
captureDialog(DebuggerCopyIntoProgramDialog.class);
}
@Test
public void testRemoteTargets_GdbOverSsh() throws Throwable {
performAction("Connect", PluginUtils.getPluginNameFromClass(DebuggerTargetsPlugin.class),
false);
DebuggerConnectDialog dialog = waitForDialogComponent(DebuggerConnectDialog.class);
runSwing(() -> dialog.setFactoryByBrief("gdb via SSH"));
captureDialog(dialog);
}
@Test
public void testRemoteTargets_Gadp() throws Throwable {
performAction("Connect", PluginUtils.getPluginNameFromClass(DebuggerTargetsPlugin.class),
false);
DebuggerConnectDialog dialog = waitForDialogComponent(DebuggerConnectDialog.class);
runSwing(() -> dialog.setFactoryByBrief("Ghidra debug agent (GADP)"));
captureDialog(dialog);
}
protected Function findCommandLineParser() throws Throwable {
for (Data data : program.getListing().getDefinedData(true)) {
Object value = data.getValue();
if (!(value instanceof String str) || !str.startsWith("Usage: ")) {
continue;
}
for (Reference refToUsage : data.getReferenceIteratorTo()) {
Address from = refToUsage.getFromAddress();
Function function = program.getFunctionManager().getFunctionContaining(from);
if (function != null) {
return function;
}
}
}
throw new AssertionError("Cannot find command-line parsing function");
}
protected CodeViewerProvider getCodeViewerProvider() {
return (CodeViewerProvider) staticListingService.getNavigatable(); // HACK
}
protected void goToStaticUntilContext(Address address) {
CodeViewerProvider provider = getCodeViewerProvider();
waitForCondition(() -> {
goTo(tool, program, address);
runSwing(() -> provider.contextChanged());
return provider.getActionContext(null) instanceof ProgramLocationActionContext;
});
}
protected void emulateCommandLineParser() throws Throwable {
Function function = findCommandLineParser();
goToStaticUntilContext(function.getEntryPoint());
performAction(EmulateProgramAction.NAME,
PluginUtils.getPluginNameFromClass(DebuggerEmulationServicePlugin.class),
getCodeViewerProvider(), true);
}
@Test
public void testEmulation_LazyStaleListing() throws Throwable {
emulateCommandLineParser();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerListingProvider.class);
}
@Test
public void testEmulation_ListingAfterResume() throws Throwable {
emulateCommandLineParser();
DebuggerListingProvider listing = getProvider(DebuggerListingProvider.class);
listing.setAutoReadMemorySpec(
AutoReadMemorySpec.fromConfigName(LoadEmulatorAutoReadMemorySpec.CONFIG_NAME));
EmulationResult result = flatDbg.getEmulationService()
.run(flatDbg.getCurrentPlatform(), flatDbg.getCurrentEmulationSchedule(), monitor,
Scheduler.oneThread(flatDbg.getCurrentThread()));
flatDbg.getTraceManager().activateTime(result.schedule());
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerListingProvider.class);
}
protected void addWatchesForCmdline() throws Throwable {
DebuggerWatchesService watchesService = tool.getService(DebuggerWatchesService.class);
watchesService.addWatch("RSP");
watchesService.addWatch("RDI");
watchesService.addWatch("RSI");
watchesService.addWatch("*:8 (RSI + 0)");
watchesService.addWatch("*:8 (RSI + 8)");
watchesService.addWatch("*:8 (RSI + 16)");
watchesService.addWatch("*:30 (*:8 (RSI + 0))")
.setDataType(TerminatedStringDataType.dataType);
watchesService.addWatch("*:30 (*:8 (RSI + 8))")
.setDataType(TerminatedStringDataType.dataType);
watchesService.addWatch("*:30 (*:8 (RSI + 16))")
.setDataType(TerminatedStringDataType.dataType);
}
@Test
public void testEmulation_WatchesForCmdline() throws Throwable {
emulateCommandLineParser();
addWatchesForCmdline();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerWatchesProvider.class);
}
protected void activateCmdlinePatchedSchedule() throws Throwable {
TracePlatform platform = flatDbg.getCurrentPlatform();
Address forArgv0 = platform.getAddressFactory().getAddress("00001018");
Address forArgv1 = forArgv0.add("termmines\0".length());
Address forArgv2 = forArgv1.add("-s\0".length());
List<String> sleigh = new ArrayList<>();
sleigh.add("RDI=3");
sleigh.add("RSI=0x1000");
sleigh.addAll(PatchStep.generateSleigh(platform.getLanguage(),
forArgv0, "termmines\0".getBytes()));
sleigh.addAll(PatchStep.generateSleigh(platform.getLanguage(),
forArgv1, "-s\0".getBytes()));
sleigh.addAll(PatchStep.generateSleigh(platform.getLanguage(),
forArgv2, "Advanced\0".getBytes()));
sleigh.add("*:8 (RSI + 0) = 0x" + forArgv0);
sleigh.add("*:8 (RSI + 8) = 0x" + forArgv1);
sleigh.add("*:8 (RSI + 16) = 0x" + forArgv2);
TraceSchedule schedule = flatDbg.getCurrentEmulationSchedule();
schedule = schedule.patched(flatDbg.getCurrentThread(), platform.getLanguage(), sleigh);
flatDbg.getTraceManager().activateTime(schedule);
getProvider(DebuggerWatchesProvider.class).waitEvaluate(1000);
}
@Test
public void testEmulation_WatchesForCmdlineSet() throws Throwable {
emulateCommandLineParser();
addWatchesForCmdline();
activateCmdlinePatchedSchedule();
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerWatchesProvider.class);
}
@Test
public void testEmulation_ListingForCmdlineSet() throws Throwable {
emulateCommandLineParser();
activateCmdlinePatchedSchedule();
Address addrArgv = flatDbg.getCurrentPlatform().getAddressFactory().getAddress("00001000");
TraceProgramView view = flatDbg.getCurrentView();
waitForCondition(() -> view.getSnap() != 0);
try (Transaction tx = view.openTransaction("Place units")) {
Listing listing = view.getListing();
Data datArgv =
listing.createData(addrArgv, new ArrayDataType(PointerDataType.dataType, 3, 8));
Address forArgv0 = (Address) datArgv.getComponent(0).getValue();
Address forArgv1 = (Address) datArgv.getComponent(1).getValue();
Address forArgv2 = (Address) datArgv.getComponent(2).getValue();
listing.createData(forArgv0, TerminatedStringDataType.dataType);
listing.createData(forArgv1, TerminatedStringDataType.dataType);
listing.createData(forArgv2, TerminatedStringDataType.dataType);
}
flatDbg.goToDynamic("00001010");
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerListingProvider.class);
}
@Test
public void testEmulation_PcodeStepper() throws Throwable {
runSwing(() -> tool.setSize(1920, 1080));
addPlugin(tool, DebuggerPcodeStepperPlugin.class);
emulateCommandLineParser();
flatDbg.stepEmuPcodeOp(1, monitor);
captureProvider(DebuggerPcodeStepperProvider.class);
}
}