diff --git a/Ghidra/Debug/Debugger/certification.manifest b/Ghidra/Debug/Debugger/certification.manifest index 6210059af1..e813f80d23 100644 --- a/Ghidra/Debug/Debugger/certification.manifest +++ b/Ghidra/Debug/Debugger/certification.manifest @@ -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| diff --git a/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml b/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml index 1045bbc448..0e27f90481 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml @@ -176,10 +176,6 @@ - - diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBots/DebuggerBots.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBots/DebuggerBots.html deleted file mode 100644 index 76556d8e89..0000000000 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBots/DebuggerBots.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - Debugger Bots - - - - - -

Debugger Bots: Workflow Automation

- -

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 Edit → Tool - Options menu in Ghidra's Project window.

- -

Show Interpreter

- -

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 Console action in - the Commands and Objects window.

- -

Disassemble at Program Counter

- -

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 Disassemble command in - the Dynamic Listing window.

- -

Map Modules

- -

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 Map Modules - action in the Modules and Sections window.

- -

Map Sections

- -

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 Map Sections - action in the Modules and Sections window.

- -

Map Regions

- -

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 Map Regions - action in the Regions window.

- - diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/DebuggerBreakpointMarkerPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/DebuggerBreakpointMarkerPlugin.html index 43e4936bc2..e23b219d47 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/DebuggerBreakpointMarkerPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/DebuggerBreakpointMarkerPlugin.html @@ -35,6 +35,24 @@

By default, enabled breakpoints are colored a desaturated blue, ineffective breakpoints are colored grey, and disabled breakpoints have no background at all.

+

In the Function Graph

+ + + + + + + +
+ +

When active in the Debugger, the Function Graph 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.

+

In the Decompiler

diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerBreakpointMarkerPlugin.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerBreakpointMarkerPlugin.png index 871b2c670e..66932c2199 100644 Binary files a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerBreakpointMarkerPlugin.png and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerBreakpointMarkerPlugin.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerDecompilerBreakpointMargin.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerDecompilerBreakpointMargin.png index b0a0d584d3..df9e530f69 100644 Binary files a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerDecompilerBreakpointMargin.png and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerDecompilerBreakpointMargin.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerFunctionGraphBreakpointMargin.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerFunctionGraphBreakpointMargin.png new file mode 100644 index 0000000000..ec934cdd0a Binary files /dev/null and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerFunctionGraphBreakpointMargin.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerPlaceBreakpointDialog.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerPlaceBreakpointDialog.png index 8a98249704..f50f8b2fc2 100644 Binary files a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerPlaceBreakpointDialog.png and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerBreakpointMarkerPlugin/images/DebuggerPlaceBreakpointDialog.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerConsolePlugin/DebuggerConsolePlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerConsolePlugin/DebuggerConsolePlugin.html index 5466dc68ea..a01c5b64af 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerConsolePlugin/DebuggerConsolePlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerConsolePlugin/DebuggerConsolePlugin.html @@ -24,11 +24,8 @@

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.

+ connectors, and running agents. Soon, it may also provide a command-line interface to control + Ghidra's debugging sessions and interact with traces.

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 @@

Select None

Resets the selection, usually so table scrolling can be restored to "normal."

+ +

Cancel

+ +

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.

diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerControlPlugin/DebuggerControlPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerControlPlugin/DebuggerControlPlugin.html index 652154a25c..05ebc6adf4 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerControlPlugin/DebuggerControlPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerControlPlugin/DebuggerControlPlugin.html @@ -106,7 +106,7 @@ when the target is currently stopped. If successful the target may briefly enter the "running" state.

-

Finish

+

Step Out

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" diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html index 25d3b0d1f4..327c910ad9 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html @@ -165,6 +165,16 @@

  • *:8 (RSP+8) — The address pointed to by stack offset 8
  • +

    Auto-Disassembly

    + +

    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 Track Location 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 Disassemble command.

    +

    Auto-Sync Cursor with Static Listing

    This action is always available, but only on the primary dynamic listing. It configures diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html index e02e142170..742a5bfecd 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/DebuggerModulesPlugin.html @@ -81,20 +81,15 @@

    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.

    -

    Capture Symbols

    +

    Auto-Map

    -

    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.

    - -

    Capture Types

    - -

    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.

    +

    This action is always available. It automatically maps trace memory to static images, using + Module, Section, or Region information. See the Map Modules, Map Sections, and Map Regions + 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.

    Map Identically

    @@ -115,10 +110,9 @@

    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 Map Modules 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.

    + the Auto-Map 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.

    @@ -140,8 +134,7 @@

    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 Map Sections debugger bot.

    + Modules should also consider setting Auto-Map to use Sections.

    diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModuleMapProposalDialog.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModuleMapProposalDialog.png index b30098225d..e4feb7d5c9 100644 Binary files a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModuleMapProposalDialog.png and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModuleMapProposalDialog.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModulesPlugin.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModulesPlugin.png index 47a07227b9..72fe042d4b 100644 Binary files a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModulesPlugin.png and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerModulesPlugin.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerSectionMapProposalDialog.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerSectionMapProposalDialog.png index da54d2e0cb..8bc18a40f0 100644 Binary files a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerSectionMapProposalDialog.png and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerModulesPlugin/images/DebuggerSectionMapProposalDialog.png differ diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html index a68e29113a..baa08878b7 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html @@ -60,12 +60,13 @@

    This action is analogous to the Map Modules and Map Sections actions from the Modules window. 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 Map Regions 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.

    + Users who prefer this should also consider setting the Auto-Map 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.

    diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerStaticMappingPlugin/DebuggerStaticMappingPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerStaticMappingPlugin/DebuggerStaticMappingPlugin.html index b1247497ff..e5da1b8ae4 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerStaticMappingPlugin/DebuggerStaticMappingPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerStaticMappingPlugin/DebuggerStaticMappingPlugin.html @@ -25,12 +25,13 @@

    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 Map - Modules bot, or by higher-level user actions, e.g., the Map Modules - 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.

    + automation, e.g., the Auto-Map action, or + by manual user actions, e.g., the Map Modules. + 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.

    Table Columns

    diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java index 4b4e9a534e..c6634967f1 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/console/DebuggerConsoleProvider.java @@ -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 diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginScreenShots.java b/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginScreenShots.java index f26dfd44f8..4b7b2ed3e5 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginScreenShots.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginScreenShots.java @@ -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 getGraphUpdater(FGProvider fgProvider) { + FGPrimaryViewer viewer = getPrimaryGraphViewer(fgProvider); + if (viewer == null) { + return null; // this can happen when disposed or not on a function + } + + VisualGraphViewUpdater updater = viewer.getViewUpdater(); + assertNotNull(updater); + return updater; + } + + protected void waitForAnimation(FGController controller, FGProvider fgProvider) { + + VisualGraphViewUpdater 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();