mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Changes Program Graph actions to not graph entire program when there is no selection
This commit is contained in:
parent
5b8be18b40
commit
c02ab0160c
4 changed files with 135 additions and 65 deletions
|
@ -46,10 +46,40 @@
|
|||
program.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Graph Scope</H2>
|
||||
<P>When creating any of the graphs described below, the scope of the graph is determined by the
|
||||
current location and selection present in the listing. </P>
|
||||
<BLOCKQUOTE>
|
||||
<H3>If there is a selection:</H3>
|
||||
<BLOCKQUOTE><P> The graph will
|
||||
include all the code that is selected and exclude all the code that is not selected.</P>
|
||||
</BLOCKQUOTE>
|
||||
<H3>If there is no selection:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<P> The scope is determined by the current cursor location and the type of graph:</P>
|
||||
</BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<H4>Current Location is in a Function</H4>
|
||||
<UL>
|
||||
<LI>Block Flow Graphs: The scope is the body of the containing functions</LI>
|
||||
<LI>Call Graphs: The scope is the containing function and all the functions that
|
||||
either call it or it calls</LI>
|
||||
</UL>
|
||||
<H4>Current Location is not in a Function</H4>
|
||||
<UL>
|
||||
<LI>the scope will be the entire program</LI>
|
||||
</UL>
|
||||
</BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/tip.png"> To graph the entire program, press "<ctrl> a" to
|
||||
select all before creating the graph.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Synchronization</H2>
|
||||
|
||||
<P>Selection and Location events are synchronized between each
|
||||
graph and the other windows in the tool.
|
||||
|
||||
<H2>Selection</H2>
|
||||
<BLOCKQUOTE>
|
||||
<H3>Selection</H3>
|
||||
|
||||
<P>The current selection within the graph display is represented by a red box around selected
|
||||
nodes as shown below on the node labeled "00408133". A node is selected if any addresses it represents are contained within the
|
||||
|
@ -74,7 +104,7 @@
|
|||
from the basic blocks found within the selected subroutine.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Location</H2>
|
||||
<H3>Location</H3>
|
||||
|
||||
<P>The node containing the current address location is marked with a large red arrow as shown
|
||||
below on the graph node labeled "00408133".</P>
|
||||
|
@ -94,7 +124,7 @@
|
|||
<P align="left">Clicking on a node in the graph display causes the
|
||||
current address location within Ghidra to change to the minimum address represented by the
|
||||
graph node.</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
<H2>Graph Representation</H2>
|
||||
|
||||
<P>By Default, the graphs use the following icons and colors to represent the nodes and edges.</P>
|
||||
|
|
|
@ -21,8 +21,7 @@ import java.util.*;
|
|||
import docking.widgets.EventTrigger;
|
||||
import ghidra.app.plugin.core.colorizer.ColorizingService;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.block.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
@ -110,8 +109,9 @@ public class BlockGraphTask extends Task {
|
|||
private boolean reuseGraph;
|
||||
private boolean appendGraph;
|
||||
private PluginTool tool;
|
||||
private String actionName;
|
||||
private Program program;
|
||||
private AddressSetView graphScope;
|
||||
private String graphTitle;
|
||||
|
||||
public BlockGraphTask(String actionName, boolean graphEntryPointNexus, boolean showCode,
|
||||
boolean reuseGraph, boolean appendGraph, PluginTool tool, ProgramSelection selection,
|
||||
|
@ -119,8 +119,6 @@ public class BlockGraphTask extends Task {
|
|||
GraphDisplayProvider graphProvider) {
|
||||
|
||||
super("Graph Program", true, false, true);
|
||||
this.actionName = actionName;
|
||||
|
||||
this.graphEntryPointNexus = graphEntryPointNexus;
|
||||
this.showCode = showCode;
|
||||
this.reuseGraph = reuseGraph;
|
||||
|
@ -132,6 +130,7 @@ public class BlockGraphTask extends Task {
|
|||
this.selection = selection;
|
||||
this.location = location;
|
||||
this.program = blockModel.getProgram();
|
||||
this.graphTitle = actionName + ": ";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,6 +138,7 @@ public class BlockGraphTask extends Task {
|
|||
*/
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) throws CancelledException {
|
||||
this.graphScope = getGraphScopeAndGenerateGraphTitle();
|
||||
AttributedGraph graph = createGraph();
|
||||
monitor.setMessage("Generating Graph...");
|
||||
try {
|
||||
|
@ -153,7 +153,7 @@ public class BlockGraphTask extends Task {
|
|||
display.setVertexLabel(CODE_ATTRIBUTE, GraphDisplay.ALIGN_LEFT, 12, true,
|
||||
codeLimitPerBlock + 1);
|
||||
}
|
||||
display.setGraph(graph, getDescription(), appendGraph, monitor);
|
||||
display.setGraph(graph, graphTitle, appendGraph, monitor);
|
||||
|
||||
if (location != null) {
|
||||
// initialize the graph location, but don't have the graph send an event
|
||||
|
@ -175,17 +175,6 @@ public class BlockGraphTask extends Task {
|
|||
}
|
||||
}
|
||||
|
||||
private String getDescription() {
|
||||
String description = actionName;
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
description += ": " + selection.getMinAddress();
|
||||
}
|
||||
else {
|
||||
description += " (Entire Program)";
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of code lines which will be used per block when
|
||||
* showCode is enabled.
|
||||
|
@ -221,10 +210,62 @@ public class BlockGraphTask extends Task {
|
|||
}
|
||||
|
||||
private CodeBlockIterator getBlockIterator() throws CancelledException {
|
||||
if (selection == null || selection.isEmpty()) {
|
||||
return blockModel.getCodeBlocks(taskMonitor);
|
||||
return blockModel.getCodeBlocksContaining(graphScope, taskMonitor);
|
||||
}
|
||||
return blockModel.getCodeBlocksContaining(selection, taskMonitor);
|
||||
|
||||
private AddressSetView getGraphScopeAndGenerateGraphTitle() {
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
graphTitle += selection.getMinAddress().toString();
|
||||
return selection;
|
||||
}
|
||||
Function function = getContainingFunction(location);
|
||||
if (function != null) {
|
||||
graphTitle += function.getName();
|
||||
if (isCallGraph()) {
|
||||
return getScopeForCallGraph(function);
|
||||
}
|
||||
return function.getBody();
|
||||
}
|
||||
graphTitle += "(Entire Program)";
|
||||
return blockModel.getProgram().getMemory();
|
||||
}
|
||||
|
||||
private boolean isCallGraph() {
|
||||
return blockModel instanceof SubroutineBlockModel;
|
||||
}
|
||||
|
||||
private AddressSetView getScopeForCallGraph(Function function) {
|
||||
AddressSet set = new AddressSet();
|
||||
set.add(function.getBody());
|
||||
try {
|
||||
CodeBlock block = blockModel.getCodeBlockAt(function.getEntryPoint(), taskMonitor);
|
||||
CodeBlockReferenceIterator it = blockModel.getDestinations(block, taskMonitor);
|
||||
while (it.hasNext()) {
|
||||
CodeBlockReference next = it.next();
|
||||
set.add(next.getDestinationBlock());
|
||||
}
|
||||
it = blockModel.getSources(block, taskMonitor);
|
||||
while (it.hasNext()) {
|
||||
CodeBlockReference next = it.next();
|
||||
set.add(next.getSourceBlock());
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// just return, the task is being cancelled.
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
private Function getContainingFunction(ProgramLocation cursorLocation) {
|
||||
if (cursorLocation == null) {
|
||||
return null;
|
||||
}
|
||||
Address address = cursorLocation.getAddress();
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
return blockModel.getProgram().getFunctionManager().getFunctionContaining(address);
|
||||
}
|
||||
|
||||
private Address graphBlock(AttributedGraph graph, CodeBlock curBB,
|
||||
|
@ -285,7 +326,7 @@ public class BlockGraphTask extends Task {
|
|||
|
||||
// don't include destination if it does not overlap selection
|
||||
// always include if selection is empty
|
||||
if (selection != null && !selection.isEmpty() && !selection.intersects(db)) {
|
||||
if (graphScope != null && !graphScope.isEmpty() && !graphScope.intersects(db)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ public class BlockGraphEventTest extends AbstractBlockGraphTest {
|
|||
assertEquals("01002239", display.getFocusedVertex().getId());
|
||||
}
|
||||
|
||||
|
||||
private AddressSet addrSet(long start, long end) {
|
||||
return new AddressSet(addr(start), addr(end));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue