mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-21 19:42:14 +00:00
GP-199 allow function definitions to be applied from selected category
This commit is contained in:
parent
7f9de4251d
commit
3fc5e55d7a
@ -628,12 +628,15 @@
|
||||
Types</H3>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>You can apply all function signature data types from an archive to the currently
|
||||
open Program. Function signature definitions can also be applied from the currently
|
||||
open program's defined data types. Applying data types from the program is useful when
|
||||
<P>You can apply all function definition data types from an archive or selected category to the currently
|
||||
open Program. This can be done from the Data Type Manager tree
|
||||
by selecting the <I><B>Apply Function Data Types</B></I> popup action
|
||||
for a selected Archive or Category node.
|
||||
Function definitions can also be applied from the currently open program's defined data types.
|
||||
Applying data types from the program is useful when
|
||||
source header files have been parsed into the program instead of an archive. This
|
||||
action attempts to match the function definition with user defined symbol names in the
|
||||
Program. When a match is found, the <I><B>Apply All</B></I> action does one of the
|
||||
action attempts to match the function definition with symbol names in the
|
||||
Program. When a match is found, the <I><B>Apply Function Data Types</B></I> action does one of the
|
||||
following:<BR>
|
||||
</P>
|
||||
|
||||
@ -667,8 +670,8 @@
|
||||
within the selection will have their signatures captured.</LI>
|
||||
</UL>
|
||||
|
||||
<P>Once you have captured the function data types to an archive, you can use the <A
|
||||
href="#Apply_All">Apply Function Data Types</A> to apply the function definition data
|
||||
<P>Once you have captured the function definitions to an archive, you can use the <A
|
||||
href="#Apply_Function_Data_Types">Apply Function Data Types</A> action to apply the function definition data
|
||||
types to another program.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
@ -21,12 +21,14 @@ import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||
import ghidra.app.util.PseudoDisassembler;
|
||||
import ghidra.framework.cmd.BackgroundCommand;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
@ -37,12 +39,11 @@ import ghidra.util.task.TaskMonitor;
|
||||
public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||
private Program program;
|
||||
private BookmarkManager bookmarkMgr;
|
||||
private List<DataTypeManager> managers;
|
||||
private List<Category> sourceCategories;
|
||||
private AddressSetView addresses;
|
||||
private SourceType source;
|
||||
private boolean alwaysReplace;
|
||||
private boolean createBookmarksEnabled;
|
||||
private Map<String, FunctionDefinition> functionNameMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs a new command to apply all function signature data types
|
||||
@ -61,13 +62,45 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||
public ApplyFunctionDataTypesCmd(List<DataTypeManager> managers, AddressSetView set,
|
||||
SourceType source, boolean alwaysReplace, boolean createBookmarksEnabled) {
|
||||
super("Apply Function Data Types", true, false, false);
|
||||
this.managers = managers;
|
||||
this.sourceCategories = getRootCategories(managers);
|
||||
this.addresses = set;
|
||||
this.source = source;
|
||||
this.alwaysReplace = alwaysReplace;
|
||||
this.createBookmarksEnabled = createBookmarksEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new command to apply all function signature data types
|
||||
* in the given data type category (includes all subcategories).
|
||||
*
|
||||
* @param sourceCategory datatype category containing the function signature data types
|
||||
* @param set set of addresses containing labels to match against function names.
|
||||
* The addresses must not already be included in the body of any existing function.
|
||||
* If null, all symbols will be processed
|
||||
* @param source the source of this command.
|
||||
* @param alwaysReplace true to always replace the existing function signature with the
|
||||
* function signature data type.
|
||||
* @param createBookmarksEnabled true to create a bookmark when a function signature
|
||||
* has been applied.
|
||||
*/
|
||||
public ApplyFunctionDataTypesCmd(Category sourceCategory, AddressSetView set,
|
||||
SourceType source, boolean alwaysReplace, boolean createBookmarksEnabled) {
|
||||
super("Apply Function Data Types", true, false, false);
|
||||
this.sourceCategories = List.of(sourceCategory);
|
||||
this.addresses = set;
|
||||
this.source = source;
|
||||
this.alwaysReplace = alwaysReplace;
|
||||
this.createBookmarksEnabled = createBookmarksEnabled;
|
||||
}
|
||||
|
||||
private static List<Category> getRootCategories(List<DataTypeManager> managers) {
|
||||
List<Category> roots = new ArrayList<>();
|
||||
for (DataTypeManager dtm : managers) {
|
||||
roots.add(dtm.getRootCategory());
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||
program = (Program) obj;
|
||||
@ -77,7 +110,12 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||
|
||||
Map<String, List<Symbol>> symbolMap = createSymMap();
|
||||
|
||||
applyDataTypes(monitor, symbolMap);
|
||||
try {
|
||||
applyFunctionDefinitions(monitor, symbolMap);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// ignore and return
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -136,39 +174,23 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all descendants starting at node.
|
||||
* Apply all descendants starting at each category node.
|
||||
* @param monitor task monitor
|
||||
* @param symbolMap symbol map where possible function definitions may be applied
|
||||
* @throws CancelledException if task cancelled
|
||||
*/
|
||||
private void applyDataTypes(TaskMonitor monitor, Map<String, List<Symbol>> symbolMap) {
|
||||
|
||||
for (DataTypeManager dataTypeManager : managers) {
|
||||
Iterator<DataType> iter = dataTypeManager.getAllDataTypes();
|
||||
while (iter.hasNext()) {
|
||||
if (monitor.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DataType dt = iter.next();
|
||||
if (!(dt instanceof FunctionDefinition)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FunctionDefinition fdef = (FunctionDefinition) dt;
|
||||
String name = fdef.getName();
|
||||
if (functionNameMap.containsKey(name)) {
|
||||
FunctionDefinition dupeFdef = functionNameMap.get(name);
|
||||
if (!fdef.isEquivalent(dupeFdef)) {
|
||||
// set the functionDef to null to mark dupes
|
||||
functionNameMap.put(name, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
functionNameMap.put(name, fdef);
|
||||
}
|
||||
}
|
||||
private void applyFunctionDefinitions(TaskMonitor monitor,
|
||||
Map<String, List<Symbol>> symbolMap) throws CancelledException {
|
||||
|
||||
Map<String, FunctionDefinition> functionNameMap = new HashMap<>();
|
||||
for (Category cat : sourceCategories) {
|
||||
collectFunctionDefinitions(cat, monitor, functionNameMap);
|
||||
}
|
||||
|
||||
monitor.initialize(functionNameMap.size());
|
||||
for (String functionName : functionNameMap.keySet()) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
FunctionDefinition fdef = functionNameMap.get(functionName);
|
||||
checkForSymbol(monitor, functionName, fdef, symbolMap, null);
|
||||
|
||||
@ -180,6 +202,36 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||
|
||||
}
|
||||
|
||||
private void collectFunctionDefinitions(Category cat, TaskMonitor monitor,
|
||||
Map<String, FunctionDefinition> functionNameMap) throws CancelledException {
|
||||
|
||||
monitor.checkCanceled();
|
||||
|
||||
for (DataType dt : cat.getDataTypes()) {
|
||||
monitor.checkCanceled();
|
||||
if (!(dt instanceof FunctionDefinition)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FunctionDefinition fdef = (FunctionDefinition) dt;
|
||||
String name = fdef.getName();
|
||||
if (functionNameMap.containsKey(name)) {
|
||||
FunctionDefinition dupeFdef = functionNameMap.get(name);
|
||||
if (!fdef.isEquivalent(dupeFdef)) {
|
||||
// set the functionDef to null to mark dupes
|
||||
functionNameMap.put(name, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
functionNameMap.put(name, fdef);
|
||||
}
|
||||
}
|
||||
|
||||
for (Category subcat : cat.getCategories()) {
|
||||
collectFunctionDefinitions(subcat, monitor, functionNameMap);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForSymbol(TaskMonitor monitor, String functionName, FunctionDefinition fdef,
|
||||
Map<String, List<Symbol>> symbolMap, String prefix) {
|
||||
|
||||
@ -330,7 +382,7 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||
}
|
||||
|
||||
private SourceType getMostTrustedParameterSource(Function func) {
|
||||
SourceType highestSource = SourceType.DEFAULT;
|
||||
SourceType highestSource = func.getSignatureSource();
|
||||
Parameter[] parameters = func.getParameters();
|
||||
for (Parameter parameter : parameters) {
|
||||
SourceType paramSource = parameter.getSource();
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.datamgr.actions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import docking.ActionContext;
|
||||
@ -30,7 +27,6 @@ import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||
import ghidra.app.plugin.core.datamgr.DataTypesActionContext;
|
||||
import ghidra.app.plugin.core.datamgr.tree.*;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
|
||||
@ -66,6 +62,12 @@ public class ApplyFunctionDataTypesAction extends DockingAction {
|
||||
}
|
||||
|
||||
GTreeNode node = (GTreeNode) selectionPaths[0].getLastPathComponent();
|
||||
|
||||
if (node instanceof CategoryNode) {
|
||||
CategoryNode catNode = (CategoryNode) node;
|
||||
node = catNode.getArchiveNode();
|
||||
}
|
||||
|
||||
return (node instanceof FileArchiveNode) || (node instanceof ProjectArchiveNode) ||
|
||||
(node instanceof ProgramArchiveNode);
|
||||
}
|
||||
@ -74,14 +76,12 @@ public class ApplyFunctionDataTypesAction extends DockingAction {
|
||||
public void actionPerformed(ActionContext context) {
|
||||
GTree gTree = (GTree) context.getContextObject();
|
||||
TreePath selectionPath = gTree.getSelectionPath();
|
||||
ArchiveNode node = (ArchiveNode) selectionPath.getLastPathComponent();
|
||||
CategoryNode node = (CategoryNode) selectionPath.getLastPathComponent();
|
||||
|
||||
Program program = plugin.getProgram();
|
||||
DataTypeManager manager = node.getArchive().getDataTypeManager();
|
||||
List<DataTypeManager> managerList = new ArrayList<DataTypeManager>();
|
||||
managerList.add(manager);
|
||||
ApplyFunctionDataTypesCmd cmd =
|
||||
new ApplyFunctionDataTypesCmd(managerList, null, SourceType.USER_DEFINED, true, true);
|
||||
new ApplyFunctionDataTypesCmd(node.getCategory(), null, SourceType.USER_DEFINED, true,
|
||||
true);
|
||||
PluginTool tool = plugin.getTool();
|
||||
tool.executeBackgroundCommand(cmd, program);
|
||||
}
|
||||
|
@ -208,7 +208,8 @@
|
||||
<ul>
|
||||
<li>Users can create a function definition data type for function signatures they might want apply again in a new program for a particular named function. To do this, click on a function signature and choose Function->Create Function Definition from the Listing right mouse menu.</li>
|
||||
<li>Users can create function definitions for their whole program by choosing Capture Function Data Types from the Data Type Manager right mouse menu.</li>
|
||||
<li>In new program, apply function signature by right mousing on appropriate folder in Data Type Manager and choosing Apply Function Data Types</li>
|
||||
<li>In new program, apply function signatures by right mouse-clicking on an appropriate category folder in the Data Type Manager and
|
||||
choosing <b>Apply Function Data Types</b> from the popup menu.</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
Loading…
Reference in New Issue
Block a user