GP-4101: Update Debugger help
@ -11,10 +11,10 @@ src/main/help/help/TOC_Source.xml||GHIDRA||||END|
|
||||
src/main/help/help/topics/Debugger/Debugger.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/Debugger/GettingStarted.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/Debugger/Troubleshooting.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBots/DebuggerBots.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/DebuggerBreakpointMarkerPlugin.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerBreakpointMarkerPlugin.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerDecompilerBreakpointMargin.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerFunctionGraphBreakpointMargin.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerPlaceBreakpointDialog.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointsPlugin/DebuggerBreakpointsPlugin.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/DebuggerBreakpointsPlugin/images/DebuggerBreakpointsPlugin.png||GHIDRA||||END|
|
||||
@ -141,7 +141,6 @@ src/main/resources/images/stepover.png||GHIDRA||||END|
|
||||
src/main/resources/images/system-switch-user.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
|
||||
src/main/resources/images/thread.png||GHIDRA||||END|
|
||||
src/main/resources/images/time.png||FAMFAMFAM Icons - CC 2.5||||END|
|
||||
src/main/resources/images/write-disabled.png||GHIDRA||||END|
|
||||
src/main/resources/images/write-emulator.png||GHIDRA||||END|
|
||||
src/main/resources/images/write-target.png||GHIDRA||||END|
|
||||
src/main/resources/images/write-trace.png||Tango Icons - Public Domain||||END|
|
||||
|
@ -176,10 +176,6 @@
|
||||
<tocdef id="DebuggerPlatformPlugin" text="Platform Selection"
|
||||
sortgroup="p2"
|
||||
target="help/topics/DebuggerPlatformPlugin/DebuggerPlatformPlugin.html" />
|
||||
|
||||
<tocdef id="DebuggerBots" text="Bots: Workflow Automation"
|
||||
sortgroup="q"
|
||||
target="help/topics/DebuggerBots/DebuggerBots.html" />
|
||||
</tocdef>
|
||||
</tocref>
|
||||
</tocroot>
|
||||
|
@ -1,73 +0,0 @@
|
||||
<!DOCTYPE doctype PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META name="generator" content=
|
||||
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
|
||||
|
||||
<TITLE>Debugger Bots</TITLE>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY lang="EN-US">
|
||||
<H1>Debugger Bots: Workflow Automation</H1>
|
||||
|
||||
<P>Bots are a pluggable part of the Debugger's Workflow plugin and provide useful automation,
|
||||
taking actions on the user's behalf that would otherwise be tedious, or that should occur
|
||||
"under the hood." Each can be toggled from the <SPAN class="menu">Edit → Tool
|
||||
Options</SPAN> menu in Ghidra's <EM>Project</EM> window.</P>
|
||||
|
||||
<H2><A name="show_interpreter"></A>Show Interpreter</H2>
|
||||
|
||||
<P>This bot automatically displays the interpreter console for new debugger connections. If a
|
||||
connection does not present an interpreter, then this bot will take no action. This action can
|
||||
be performed manually using the <A href=
|
||||
"help/topics/DebuggerObjectsPlugin/DebuggerObjectsPlugin.html#console">Console</A> action in
|
||||
the Commands and Objects window.</P>
|
||||
|
||||
<H2><A name="disassemble_at_pc"></A>Disassemble at Program Counter</H2>
|
||||
|
||||
<P>This bot automatically disassembles trace memory, starting at the program counter. It is
|
||||
activated whenever an open trace's memory or program counters change. If the target presents a
|
||||
stack, then the bot will prefer to use the program counter recorded in the innermost frame 0.
|
||||
Otherwise, it will use the value of the program counter register. To accommodate multi-threaded
|
||||
traces, the bot considers all threads when responding to memory changes. It considers only the
|
||||
affected thread for program counter changes. This action can be performed manually using the <A
|
||||
href="help/topics/DisassemblerPlugin/Disassembly.htm#Disassemble">Disassemble</A> command in
|
||||
the Dynamic Listing window.</P>
|
||||
|
||||
<H2><A name="map_modules"></A>Map Modules</H2>
|
||||
|
||||
<P>This bot automatically maps trace modules to programs opened in the same tool. It is
|
||||
activated whenever a trace or program is opened, or when an opened trace's modules change. For
|
||||
a given trace, this bot considers only those modules not already mapped, seeking suitable
|
||||
programs open in the same tool. If the trace is open in multiple tools (not common) the bot
|
||||
will consider programs from all such tools where the workflow plugin is enabled. This action
|
||||
can be performed manually using the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html#map_modules">Map Modules</A>
|
||||
action in the Modules and Sections window.</P>
|
||||
|
||||
<H2><A name="map_sections"></A>Map Sections</H2>
|
||||
|
||||
<P>This bot automatically maps trace sections to memory blocks of programs opened in the same
|
||||
tool. Its operation is analogous to that of the Map Modules Bot, except that it creates the
|
||||
mapped ranges by section. It is not commonly used, as it's less efficient than the Map Modules
|
||||
Bot, but it is required whenever a target presents sections which can be relocated
|
||||
independently of other sections in the same module. This is more common in abstract machines,
|
||||
such as the Java Virtual Machine, where each method is a "section." This action can be
|
||||
performed manually using the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html#map_sections">Map Sections</A>
|
||||
action in the Modules and Sections window.</P>
|
||||
|
||||
<H2><A name="map_regions"></A>Map Regions</H2>
|
||||
|
||||
<P>This bot automatically maps trace regions to memory blocks of programs opened in the same
|
||||
tool. Its operation is analogous to that of the Map Modules Bot, except that it creates the
|
||||
mapped ranges by region. It is not commonly used, as it's less efficient than the Map Modules
|
||||
Bot, but it is required whenever a target fails to present modules. This action can be
|
||||
performed manually using the <A href=
|
||||
"help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html#map_regions">Map Regions</A>
|
||||
action in the Regions window.</P>
|
||||
</BODY>
|
||||
</HTML>
|
@ -35,6 +35,24 @@
|
||||
<P>By default, enabled breakpoints are colored a desaturated blue, ineffective breakpoints are
|
||||
colored grey, and disabled breakpoints have no background at all.</P>
|
||||
|
||||
<H2>In the Function Graph</H2>
|
||||
|
||||
<TABLE width="100%">
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD align="center" width="100%"><IMG alt="" border="1" src=
|
||||
"images/DebuggerFunctionGraphBreakpointMargin.png"></TD>
|
||||
</TR>
|
||||
</TBODY>
|
||||
</TABLE>
|
||||
|
||||
<P>When active in the Debugger, the <A href=
|
||||
"help/topics/FunctionGraphPlugin/Function_Graph.html">Function Graph</A> will display
|
||||
breakpoints using background colors and markers in each vertex's margin. The margin behaves
|
||||
exactly as it would in the static listing. A marker is displayed at each address with a
|
||||
breakpoint indicating its state. Multiple breakpoints at an address may result in display of a
|
||||
mixed state. Double clicking in the margin will set or toggle a breakpoint at that address.</P>
|
||||
|
||||
<H2>In the Decompiler</H2>
|
||||
|
||||
<TABLE width="100%">
|
||||
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 7.0 KiB |
@ -24,11 +24,8 @@
|
||||
|
||||
<P>The console logs messages from Ghidra related to the debugger. Depending on the exact
|
||||
configuration, this can comprise a wide range of components, including all GUI views, active
|
||||
connectors, and running agents. Currently, it implements an appender to gather all Log4J
|
||||
messages emitted by Ghidra and filters for debugger-related packages and a level in the range
|
||||
INFO through FATAL, inclusive. That feature will likely be removed as more components are
|
||||
programmed to work directly with the console. Soon, it may also provide a command-line
|
||||
interface to control Ghidra's debugging sessions and interact with traces.</P>
|
||||
connectors, and running agents. Soon, it may also provide a command-line interface to control
|
||||
Ghidra's debugging sessions and interact with traces.</P>
|
||||
|
||||
<P>Some log messages include an action context, allowing plug-ins to offer actions on that
|
||||
message. These are said to be "actionable" messages. A noteworthy example is when navigating to
|
||||
@ -68,5 +65,10 @@
|
||||
<H3><A name="select_none"></A>Select None</H3>
|
||||
|
||||
<P>Resets the selection, usually so table scrolling can be restored to "normal."</P>
|
||||
|
||||
<H3><A name="cancel"></A>Cancel</H3>
|
||||
|
||||
<P>Some experimental features may display progress entries in the log for background tasks they
|
||||
run. This action is displayed in the Actions column and will cancel the task.</P>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
@ -106,7 +106,7 @@
|
||||
when the target is currently stopped. If successful the target may briefly enter the "running"
|
||||
state.</P>
|
||||
|
||||
<H3><A name="target_step_finish"></A><IMG alt="" src="images/stepout.png"> Finish</H3>
|
||||
<H3><A name="target_step_out"></A><IMG alt="" src="images/stepout.png"> Step Out</H3>
|
||||
|
||||
<P>Allow the current target to finish the current subroutine, pausing after. This is available
|
||||
when the target is currently stopped. If successful the target may briefly enter the "running"
|
||||
|
@ -165,6 +165,16 @@
|
||||
<LI><CODE>*:8 (RSP+8)</CODE> — The address pointed to by stack offset 8</LI>
|
||||
</UL>
|
||||
|
||||
<H3><A name="auto_disassembly"></A>Auto-Disassembly</H3>
|
||||
|
||||
<P>This action is always available. It automatically disassembles starting at the current
|
||||
program counter. It applies only when a "Track Program Counter" option is selected in the <A
|
||||
href="#track_location">Track Location</A> action. Disassembly occurs whenever the program
|
||||
counter is updated, when the memory at the program counter is updated, or when navigating to a
|
||||
new context. It terminates at the first branch encountered. Disassembly can be performed
|
||||
manually using the <A href=
|
||||
"help/topics/DisassemblerPlugin/Disassembly.htm#Disassemble">Disassemble</A> command.</P>
|
||||
|
||||
<H3><A name="auto_sync_cursor_static"></A>Auto-Sync Cursor with Static Listing</H3>
|
||||
|
||||
<P>This action is always available, but only on the primary dynamic listing. It configures
|
||||
|
@ -81,20 +81,15 @@
|
||||
<P>This action is available from a module's or section's pop-up menu. It prompts the user to
|
||||
import the module from the local file system into Ghidra as a static image.</P>
|
||||
|
||||
<H3><A name="capture_symbols"></A>Capture Symbols</H3>
|
||||
<H3><A name="auto_map"></A>Auto-Map</H3>
|
||||
|
||||
<P>This action is available when the current trace is associated with a live target and "at the
|
||||
present," and at least one module is selected. It commands the recorder to copy all symbols
|
||||
(that the debugger knows about) for the selected modules into the trace. These are often the
|
||||
same symbols that Ghidra imports from the static image, anyway.</P>
|
||||
|
||||
<H3><A name="capture_types"></A>Capture Types</H3>
|
||||
|
||||
<P>This action is available when the current trace is associated with a live target and "at the
|
||||
present," the target presents type information, and at least one module is selected. It
|
||||
commands the recorder to copy and convert all types (that the debugger knows about) for the
|
||||
selected modules to Ghidra data types in the trace. These are often the same types that Ghidra
|
||||
imports from the static image, anyway.</P>
|
||||
<P>This action is always available. It automatically maps trace memory to static images, using
|
||||
Module, Section, or Region information. See the <A href="#map_modules">Map Modules</A>, <A
|
||||
href="#map_sections">Map Sections</A>, and <A href=
|
||||
"help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html#map_regions">Map Regions</A>
|
||||
actions for more information. When enabled, this action will automatically perform the
|
||||
corresponding action whenever the relevant table is updated. By default, it automatically maps
|
||||
using Modules.</P>
|
||||
|
||||
<H3><A name="map_identically"></A>Map Identically</H3>
|
||||
|
||||
@ -115,10 +110,9 @@
|
||||
<P>This action is available from the modules' or sections' pop-up menu. It searches the tool's
|
||||
open programs for the selected modules and proposes new mappings. The user can examine and
|
||||
tweak the proposal before confirming or canceling it. Typically, this is done automatically by
|
||||
the <A href="help/topics/DebuggerBots/DebuggerBots.html#map_modules">Map Modules</A> debugger
|
||||
bot. By selecting "Memorize" and confirming the dialog, the user can cause the mapper to re-use
|
||||
the memorized mapping in future sessions. The memorized module name is saved to the program
|
||||
database.</P>
|
||||
the <A href="#auto_map">Auto-Map</A> action. By selecting "Memorize" and confirming the dialog,
|
||||
the user can cause the mapper to re-use the memorized mapping in future sessions. The memorized
|
||||
module name is saved to the program database.</P>
|
||||
|
||||
<TABLE width="100%">
|
||||
<TBODY>
|
||||
@ -140,8 +134,7 @@
|
||||
|
||||
<P>This action is analogous to the Map Modules action. It searches the tool's open programs for
|
||||
blocks matching the selected sections and proposes new mappings. Users who prefer this to Map
|
||||
Modules should also consider using the <A href=
|
||||
"help/topics/DebuggerBots/DebuggerBots.html#map_sections">Map Sections</A> debugger bot.</P>
|
||||
Modules should also consider setting <A href="#auto_map">Auto-Map</A> to use Sections.</P>
|
||||
|
||||
<TABLE width="100%">
|
||||
<TBODY>
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 19 KiB |
@ -60,12 +60,13 @@
|
||||
<P>This action is analogous to the Map Modules and Map Sections actions from the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html">Modules window</A>. It searches
|
||||
the tool's open programs for blocks matching the selected regions and proposes new mappings.
|
||||
Users who prefer this should also consider using the <A href=
|
||||
"help/topics/DebuggerBots/DebuggerBots.html#map_regions">Map Regions</A> debugger bot. For the
|
||||
best result, the selection regions should comprise a complete module. In particular, it should
|
||||
include the region containing the module's image base, as the offset from this base is used in
|
||||
scoring the best-matched blocks. Additionally, the region names must include the module's file
|
||||
name, otherwise the matcher has no means to identify a corresponding program.</P>
|
||||
Users who prefer this should also consider setting the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html#auto_map">Auto-Map</A> action to
|
||||
use Regions. For the best result, the selection regions should comprise a complete module. In
|
||||
particular, it should include the region containing the module's image base, because the offset
|
||||
from this base is used in scoring the best-matched blocks. Additionally, the region names must
|
||||
include the module's file name, otherwise the matcher has no means to identify a corresponding
|
||||
program.</P>
|
||||
|
||||
<TABLE width="100%">
|
||||
<TBODY>
|
||||
|
@ -25,12 +25,13 @@
|
||||
<P>A static mapping refers to a range of addresses in the dynamic listing and its corresponding
|
||||
range in the static listing. These mappings provide a flexible means of mapping imported
|
||||
images, i.e., Ghidra Program Databases, into a trace. Typically, this table is populated by
|
||||
automation, e.g., the <A href="help/topics/DebuggerBots/DebuggerBots.html#map_modules">Map
|
||||
Modules</A> bot, or by higher-level user actions, e.g., the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html#map_modules">Map Modules</A>
|
||||
action. This under-the-hood static mapping window displays the mappings table, allowing users
|
||||
or developers to diagnose image mapping issues and manually add mappings, regardless of
|
||||
reported modules and/or sections. For most users, there is no reason to access this window.</P>
|
||||
automation, e.g., the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html#auto_map">Auto-Map</A> action, or
|
||||
by manual user actions, e.g., the <A href=
|
||||
"help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html#map_modules">Map Modules</A>.
|
||||
This under-the-hood static mapping window displays the mappings table, allowing users or
|
||||
developers to diagnose image mapping issues and manually add mappings, regardless of reported
|
||||
modules and/or sections. For most users, there is no reason to access this window.</P>
|
||||
|
||||
<H2>Table Columns</H2>
|
||||
|
||||
|
@ -334,10 +334,12 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
||||
|
||||
static class CancelAction extends DockingAction {
|
||||
static final Icon ICON = Icons.STOP_ICON;
|
||||
static final String HELP_ANCHOR = "cancel";
|
||||
|
||||
public CancelAction(Plugin owner) {
|
||||
super("Cancel", owner.getName());
|
||||
setToolBarData(new ToolBarData(ICON));
|
||||
setHelpLocation(new HelpLocation(owner.getName(), HELP_ANCHOR));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,14 +15,22 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.breakpoint;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import db.Transaction;
|
||||
import docking.DefaultActionContext;
|
||||
import docking.menu.ActionState;
|
||||
import docking.menu.MultiStateDockingAction;
|
||||
import generic.Unique;
|
||||
import generic.test.TestUtils;
|
||||
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;
|
||||
@ -31,6 +39,11 @@ import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingService
|
||||
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.functiongraph.FGProvider;
|
||||
import ghidra.app.plugin.core.functiongraph.FunctionGraphPlugin;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.*;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex;
|
||||
import ghidra.app.plugin.core.functiongraph.mvc.*;
|
||||
import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||
@ -39,6 +52,7 @@ 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.graph.viewer.VisualGraphViewUpdater;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
@ -46,6 +60,7 @@ import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.task.RunManager;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
|
||||
@ -85,6 +100,8 @@ public class DebuggerBreakpointMarkerPluginScreenShots extends GhidraScreenShotG
|
||||
public void testCaptureDebuggerBreakpointMarkerPlugin() throws Throwable {
|
||||
ListingPanel panel = listing.getListingPanel();
|
||||
|
||||
moveProviderToItsOwnWindow(listing, 1024, 680);
|
||||
|
||||
mb.createTestModel();
|
||||
modelService.addModel(mb.testModel);
|
||||
mb.createTestProcessesAndThreads();
|
||||
@ -114,6 +131,7 @@ public class DebuggerBreakpointMarkerPluginScreenShots extends GhidraScreenShotG
|
||||
Msg.debug(this, "Disabling breakpoint");
|
||||
LogicalBreakpoint lb = waitForValue(() -> Unique.assertAtMostOne(
|
||||
breakpointService.getBreakpointsAt(program, addr(program, 0x00401c60))));
|
||||
waitForCondition(() -> lb.computeState() == State.ENABLED);
|
||||
|
||||
lb.disable();
|
||||
waitForCondition(() -> lb.computeState() == State.DISABLED);
|
||||
@ -133,6 +151,152 @@ public class DebuggerBreakpointMarkerPluginScreenShots extends GhidraScreenShotG
|
||||
captureProviderWithScreenShot(listing);
|
||||
}
|
||||
|
||||
protected FGController getFunctionGraphController(FGProvider fgProvider) {
|
||||
return (FGController) TestUtils.getInstanceField("controller", fgProvider);
|
||||
}
|
||||
|
||||
protected void waitForBusyRunManager(FGController controller) {
|
||||
FGModel model = controller.getModel();
|
||||
|
||||
// long start = System.nanoTime();
|
||||
waitForSwing();
|
||||
RunManager runManager = (RunManager) TestUtils.getInstanceField("runManager", model);
|
||||
|
||||
waitForCondition(() -> !runManager.isInProgress());
|
||||
// long end = System.nanoTime();
|
||||
// long total = end - start;
|
||||
// Msg.debug(this,
|
||||
// "Run manager wait time: " + TimeUnit.MILLISECONDS.convert(total, TimeUnit.NANOSECONDS));
|
||||
}
|
||||
|
||||
protected FGComponent getGraphComponent(FGProvider fgProvider) {
|
||||
FGController controller =
|
||||
(FGController) TestUtils.getInstanceField("controller", fgProvider);
|
||||
FGView view = (FGView) TestUtils.getInstanceField("view", controller);
|
||||
return (FGComponent) TestUtils.getInstanceField("fgComponent", view);
|
||||
}
|
||||
|
||||
protected FGPrimaryViewer getPrimaryGraphViewer(FGProvider fgProvider) {
|
||||
FGComponent component = getGraphComponent(fgProvider);
|
||||
if (component == null) {
|
||||
return null; // this will be null if the graph has been disposed
|
||||
}
|
||||
|
||||
assertNotNull("FG GraphComponent should not be null", component);
|
||||
return (FGPrimaryViewer) getInstanceField("primaryViewer", component);
|
||||
}
|
||||
|
||||
protected VisualGraphViewUpdater<FGVertex, FGEdge> getGraphUpdater(FGProvider fgProvider) {
|
||||
FGPrimaryViewer viewer = getPrimaryGraphViewer(fgProvider);
|
||||
if (viewer == null) {
|
||||
return null; // this can happen when disposed or not on a function
|
||||
}
|
||||
|
||||
VisualGraphViewUpdater<FGVertex, FGEdge> updater = viewer.getViewUpdater();
|
||||
assertNotNull(updater);
|
||||
return updater;
|
||||
}
|
||||
|
||||
protected void waitForAnimation(FGController controller, FGProvider fgProvider) {
|
||||
|
||||
VisualGraphViewUpdater<FGVertex, FGEdge> updater = getGraphUpdater(fgProvider);
|
||||
if (updater == null) {
|
||||
return; // nothing to wait for; no active graph
|
||||
}
|
||||
|
||||
// long start = System.nanoTime();
|
||||
|
||||
waitForSwing();
|
||||
|
||||
int tryCount = 3;
|
||||
while (tryCount++ < 5 && updater.isBusy()) {
|
||||
waitForConditionWithoutFailing(() -> !updater.isBusy());
|
||||
}
|
||||
waitForSwing();
|
||||
|
||||
assertFalse(updater.isBusy());
|
||||
|
||||
// long end = System.nanoTime();
|
||||
// long total = end - start;
|
||||
// Msg.debug(this,
|
||||
// "Animation wait time: " + TimeUnit.MILLISECONDS.convert(total, TimeUnit.NANOSECONDS));
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void setGraphLayout(FGProvider fgProvider) {
|
||||
long start = System.currentTimeMillis();
|
||||
Object actionManager = getInstanceField("actionManager", fgProvider);
|
||||
final MultiStateDockingAction<?> action =
|
||||
(MultiStateDockingAction<?>) getInstanceField("layoutAction", actionManager);
|
||||
|
||||
Object minCrossState = null;
|
||||
List<?> states = action.getAllActionStates();
|
||||
for (Object state : states) {
|
||||
if (((ActionState) state).getName().indexOf("Nested Code Layout") != -1) {
|
||||
minCrossState = state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertNotNull("Could not find min cross layout!", minCrossState);
|
||||
|
||||
//@formatter:off
|
||||
invokeInstanceMethod( "setCurrentActionState",
|
||||
action,
|
||||
new Class<?>[] { ActionState.class },
|
||||
new Object[] { minCrossState });
|
||||
//@formatter:on
|
||||
|
||||
runSwing(() -> action.actionPerformed(new DefaultActionContext()));
|
||||
|
||||
// wait for the threaded graph layout code
|
||||
FGController controller = getFunctionGraphController(fgProvider);
|
||||
waitForBusyRunManager(controller);
|
||||
waitForAnimation(controller, fgProvider);
|
||||
getPrimaryGraphViewer(fgProvider).repaint();
|
||||
waitForSwing();
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
Msg.debug(this, "relayout time: " + ((end - start) / 1000.0) + "s");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptureDebuggerFunctionGraphBreakpointMargin() 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, FunctionGraphPlugin.class);
|
||||
|
||||
FGProvider fgProvider = waitForComponentProvider(FGProvider.class);
|
||||
Swing.runNow(() -> tool.showComponentProvider(fgProvider, true));
|
||||
setGraphLayout(fgProvider);
|
||||
goTo(tool, program, addr(program, 0x00401070));
|
||||
captureIsolatedProvider(fgProvider, 700, 700);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptureDebuggerDecompilerBreakpointMargin() throws Throwable {
|
||||
mb.createTestModel();
|
||||
|