mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-3837: Update Debugger Help for Trace RMI.
This commit is contained in:
parent
6c60bd0313
commit
c634283544
134 changed files with 3214 additions and 1550 deletions
|
@ -15,37 +15,43 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.breakpoint;
|
||||
|
||||
import static ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest.waitForPass;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.List;
|
||||
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.control.MockTarget;
|
||||
import ghidra.app.plugin.core.debug.service.emulation.ProgramEmulationUtils;
|
||||
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.target.DebuggerTargetServicePlugin;
|
||||
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.framework.model.DomainFolder;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.database.breakpoint.DBTraceBreakpointManager;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
|
@ -53,8 +59,7 @@ import help.screenshot.GhidraScreenShotGenerator;
|
|||
public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenerator
|
||||
implements DebuggerModelTestUtils {
|
||||
|
||||
TestDebuggerModelBuilder mb = new TestDebuggerModelBuilder();
|
||||
DebuggerModelServiceProxyPlugin modelService;
|
||||
DebuggerTargetService targetService;
|
||||
DebuggerStaticMappingService mappingService;
|
||||
DebuggerLogicalBreakpointService breakpointService;
|
||||
DebuggerTraceManagerService traceManager;
|
||||
|
@ -73,7 +78,7 @@ public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenera
|
|||
@Before
|
||||
public void setUpMine() throws Exception {
|
||||
breakpointService = addPlugin(tool, DebuggerLogicalBreakpointServicePlugin.class);
|
||||
modelService = addPlugin(tool, DebuggerModelServiceProxyPlugin.class);
|
||||
targetService = addPlugin(tool, DebuggerTargetServicePlugin.class);
|
||||
mappingService = addPlugin(tool, DebuggerStaticMappingServicePlugin.class);
|
||||
traceManager = addPlugin(tool, DebuggerTraceManagerServicePlugin.class);
|
||||
programManager = addPlugin(tool, ProgramManagerPlugin.class);
|
||||
|
@ -110,80 +115,85 @@ public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenera
|
|||
DebuggerBreakpointsProvider provider =
|
||||
waitForComponentProvider(DebuggerBreakpointsProvider.class);
|
||||
|
||||
mb.createTestModel();
|
||||
modelService.addModel(mb.testModel);
|
||||
mb.createTestProcessesAndThreads();
|
||||
try (
|
||||
ToyDBTraceBuilder tb1 =
|
||||
new ToyDBTraceBuilder("echo.1", ProgramBuilder._TOY64_BE);
|
||||
ToyDBTraceBuilder tb2 =
|
||||
new ToyDBTraceBuilder("echo.2", ProgramBuilder._TOY64_BE);) {
|
||||
|
||||
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();
|
||||
targetService.publishTarget(new MockTarget(tb1.trace));
|
||||
targetService.publishTarget(new MockTarget(tb2.trace));
|
||||
DomainFolder root = tool.getProject().getProjectData().getRootFolder();
|
||||
root.createFile("echo.1", tb1.trace, TaskMonitor.DUMMY);
|
||||
root.createFile("echo.2", tb2.trace, TaskMonitor.DUMMY);
|
||||
|
||||
programManager.openProgram(program);
|
||||
traceManager.openTrace(trace1);
|
||||
traceManager.openTrace(trace3);
|
||||
try (Transaction tx = tb1.startTransaction()) {
|
||||
DebuggerStaticMappingUtils.addMapping(
|
||||
new DefaultTraceLocation(tb1.trace, null, Lifespan.nowOn(0),
|
||||
addr(tb1.trace, 0x00400000)),
|
||||
new ProgramLocation(program, addr(program, 0x00400000)), 0x00210000, false);
|
||||
}
|
||||
try (Transaction tx = tb2.startTransaction()) {
|
||||
DebuggerStaticMappingUtils.addMapping(
|
||||
new DefaultTraceLocation(tb2.trace, null, Lifespan.nowOn(0),
|
||||
addr(tb2.trace, 0x7fac0000)),
|
||||
new ProgramLocation(program, addr(program, 0x00400000)), 0x00010000, false);
|
||||
}
|
||||
waitForSwing();
|
||||
|
||||
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 = 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");
|
||||
}
|
||||
|
||||
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 = tb1.startTransaction()) {
|
||||
tb1.trace.getObjectManager()
|
||||
.createRootObject(ProgramEmulationUtils.EMU_SESSION_SCHEMA);
|
||||
long snap = tb1.trace.getTimeManager().createSnapshot("First").getKey();
|
||||
|
||||
DBTraceBreakpointManager bm = tb1.trace.getBreakpointManager();
|
||||
bm.placeBreakpoint("Breakpoints[1]", snap, tb1.addr(0x00401234), List.of(),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "ram:00401234");
|
||||
bm.placeBreakpoint("Breakpoints[2]", snap, tb1.range(0x00604321, 0x00604324),
|
||||
List.of(),
|
||||
Set.of(TraceBreakpointKind.WRITE), true, "ram:00604321");
|
||||
}
|
||||
|
||||
try (Transaction tx = tb2.startTransaction()) {
|
||||
tb2.trace.getObjectManager()
|
||||
.createRootObject(ProgramEmulationUtils.EMU_SESSION_SCHEMA);
|
||||
long snap = tb2.trace.getTimeManager().createSnapshot("First").getKey();
|
||||
|
||||
DBTraceBreakpointManager bm = tb2.trace.getBreakpointManager();
|
||||
bm.placeBreakpoint("Breakpoints[1]", snap, tb2.addr(0x7fac1234), List.of(),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), false, "ram:7fac1234");
|
||||
}
|
||||
|
||||
programManager.openProgram(program);
|
||||
traceManager.openTrace(tb1.trace);
|
||||
traceManager.openTrace(tb2.trace);
|
||||
|
||||
waitForPass(() -> {
|
||||
Set<LogicalBreakpoint> allBreakpoints = breakpointService.getAllBreakpoints();
|
||||
assertEquals(2, allBreakpoints.size());
|
||||
});
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* ###
|
||||
* 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.tracermi.launcher;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.app.plugin.core.debug.gui.objects.components.DebuggerMethodInvocationDialog;
|
||||
import ghidra.app.plugin.core.terminal.TerminalProvider;
|
||||
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
|
||||
public class TraceRmiLauncherServicePluginScreenShots extends GhidraScreenShotGenerator {
|
||||
TraceRmiLauncherServicePlugin servicePlugin;
|
||||
|
||||
protected void captureLauncherByTitle(String title, Map<String, ?> args) throws Throwable {
|
||||
servicePlugin = addPlugin(tool, TraceRmiLauncherServicePlugin.class);
|
||||
|
||||
ToyProgramBuilder pb = new ToyProgramBuilder("demo", false);
|
||||
|
||||
TraceRmiLaunchOffer offer = servicePlugin.getOffers(pb.getProgram())
|
||||
.stream()
|
||||
.filter(o -> title.equals(o.getTitle()))
|
||||
.findAny()
|
||||
.orElseThrow();
|
||||
|
||||
AbstractTraceRmiLaunchOffer aoff = (AbstractTraceRmiLaunchOffer) offer;
|
||||
aoff.saveLauncherArgs(args, aoff.getParameters());
|
||||
|
||||
runSwingLater(() -> servicePlugin.configureAndLaunch(offer));
|
||||
|
||||
captureDialog(DebuggerMethodInvocationDialog.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptureGdbLauncher() throws Throwable {
|
||||
captureLauncherByTitle("gdb", Map.of("arg:1", "/home/user/demo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptureGdbTerminal() throws Throwable {
|
||||
servicePlugin = addPlugin(tool, TraceRmiLauncherServicePlugin.class);
|
||||
|
||||
TraceRmiLaunchOffer offer = servicePlugin.getOffers(null)
|
||||
.stream()
|
||||
.filter(o -> "raw gdb".equals(o.getTitle()))
|
||||
.findAny()
|
||||
.orElseThrow();
|
||||
|
||||
servicePlugin.relaunch(offer);
|
||||
|
||||
captureIsolatedProvider(TerminalProvider.class, 600, 600);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue