mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 09:17:13 +08:00
GP-199 allow function definitions to be applied from selected category
This commit is contained in:
+10
-7
@@ -628,12 +628,15 @@
|
|||||||
Types</H3>
|
Types</H3>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>You can apply all function signature data types from an archive to the currently
|
<P>You can apply all function definition data types from an archive or selected category to the currently
|
||||||
open Program. Function signature definitions can also be applied from the currently
|
open Program. This can be done from the Data Type Manager tree
|
||||||
open program's defined data types. Applying data types from the program is useful when
|
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
|
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
|
action attempts to match the function definition with symbol names in the
|
||||||
Program. When a match is found, the <I><B>Apply All</B></I> action does one of the
|
Program. When a match is found, the <I><B>Apply Function Data Types</B></I> action does one of the
|
||||||
following:<BR>
|
following:<BR>
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
@@ -667,8 +670,8 @@
|
|||||||
within the selection will have their signatures captured.</LI>
|
within the selection will have their signatures captured.</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<P>Once you have captured the function data types to an archive, you can use the <A
|
<P>Once you have captured the function definitions to an archive, you can use the <A
|
||||||
href="#Apply_All">Apply Function Data Types</A> to apply the function definition data
|
href="#Apply_Function_Data_Types">Apply Function Data Types</A> action to apply the function definition data
|
||||||
types to another program.</P>
|
types to another program.</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|||||||
+86
-34
@@ -21,12 +21,14 @@ import ghidra.app.cmd.disassemble.DisassembleCommand;
|
|||||||
import ghidra.app.util.PseudoDisassembler;
|
import ghidra.app.util.PseudoDisassembler;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
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.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,12 +39,11 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
private Program program;
|
private Program program;
|
||||||
private BookmarkManager bookmarkMgr;
|
private BookmarkManager bookmarkMgr;
|
||||||
private List<DataTypeManager> managers;
|
private List<Category> sourceCategories;
|
||||||
private AddressSetView addresses;
|
private AddressSetView addresses;
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
private boolean alwaysReplace;
|
private boolean alwaysReplace;
|
||||||
private boolean createBookmarksEnabled;
|
private boolean createBookmarksEnabled;
|
||||||
private Map<String, FunctionDefinition> functionNameMap = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command to apply all function signature data types
|
* 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,
|
public ApplyFunctionDataTypesCmd(List<DataTypeManager> managers, AddressSetView set,
|
||||||
SourceType source, boolean alwaysReplace, boolean createBookmarksEnabled) {
|
SourceType source, boolean alwaysReplace, boolean createBookmarksEnabled) {
|
||||||
super("Apply Function Data Types", true, false, false);
|
super("Apply Function Data Types", true, false, false);
|
||||||
this.managers = managers;
|
this.sourceCategories = getRootCategories(managers);
|
||||||
this.addresses = set;
|
this.addresses = set;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.alwaysReplace = alwaysReplace;
|
this.alwaysReplace = alwaysReplace;
|
||||||
this.createBookmarksEnabled = createBookmarksEnabled;
|
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
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
program = (Program) obj;
|
||||||
@@ -77,7 +110,12 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
|||||||
|
|
||||||
Map<String, List<Symbol>> symbolMap = createSymMap();
|
Map<String, List<Symbol>> symbolMap = createSymMap();
|
||||||
|
|
||||||
applyDataTypes(monitor, symbolMap);
|
try {
|
||||||
|
applyFunctionDefinitions(monitor, symbolMap);
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
// ignore and return
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
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) {
|
private void applyFunctionDefinitions(TaskMonitor monitor,
|
||||||
|
Map<String, List<Symbol>> symbolMap) throws CancelledException {
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Map<String, FunctionDefinition> functionNameMap = new HashMap<>();
|
||||||
|
for (Category cat : sourceCategories) {
|
||||||
|
collectFunctionDefinitions(cat, monitor, functionNameMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor.initialize(functionNameMap.size());
|
monitor.initialize(functionNameMap.size());
|
||||||
for (String functionName : functionNameMap.keySet()) {
|
for (String functionName : functionNameMap.keySet()) {
|
||||||
|
monitor.checkCanceled();
|
||||||
|
|
||||||
FunctionDefinition fdef = functionNameMap.get(functionName);
|
FunctionDefinition fdef = functionNameMap.get(functionName);
|
||||||
checkForSymbol(monitor, functionName, fdef, symbolMap, null);
|
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,
|
private void checkForSymbol(TaskMonitor monitor, String functionName, FunctionDefinition fdef,
|
||||||
Map<String, List<Symbol>> symbolMap, String prefix) {
|
Map<String, List<Symbol>> symbolMap, String prefix) {
|
||||||
|
|
||||||
@@ -330,7 +382,7 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SourceType getMostTrustedParameterSource(Function func) {
|
private SourceType getMostTrustedParameterSource(Function func) {
|
||||||
SourceType highestSource = SourceType.DEFAULT;
|
SourceType highestSource = func.getSignatureSource();
|
||||||
Parameter[] parameters = func.getParameters();
|
Parameter[] parameters = func.getParameters();
|
||||||
for (Parameter parameter : parameters) {
|
for (Parameter parameter : parameters) {
|
||||||
SourceType paramSource = parameter.getSource();
|
SourceType paramSource = parameter.getSource();
|
||||||
|
|||||||
+9
-9
@@ -15,9 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.datamgr.actions;
|
package ghidra.app.plugin.core.datamgr.actions;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
|
|
||||||
import docking.ActionContext;
|
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.DataTypesActionContext;
|
||||||
import ghidra.app.plugin.core.datamgr.tree.*;
|
import ghidra.app.plugin.core.datamgr.tree.*;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
|
||||||
@@ -66,6 +62,12 @@ public class ApplyFunctionDataTypesAction extends DockingAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GTreeNode node = (GTreeNode) selectionPaths[0].getLastPathComponent();
|
GTreeNode node = (GTreeNode) selectionPaths[0].getLastPathComponent();
|
||||||
|
|
||||||
|
if (node instanceof CategoryNode) {
|
||||||
|
CategoryNode catNode = (CategoryNode) node;
|
||||||
|
node = catNode.getArchiveNode();
|
||||||
|
}
|
||||||
|
|
||||||
return (node instanceof FileArchiveNode) || (node instanceof ProjectArchiveNode) ||
|
return (node instanceof FileArchiveNode) || (node instanceof ProjectArchiveNode) ||
|
||||||
(node instanceof ProgramArchiveNode);
|
(node instanceof ProgramArchiveNode);
|
||||||
}
|
}
|
||||||
@@ -74,14 +76,12 @@ public class ApplyFunctionDataTypesAction extends DockingAction {
|
|||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
GTree gTree = (GTree) context.getContextObject();
|
GTree gTree = (GTree) context.getContextObject();
|
||||||
TreePath selectionPath = gTree.getSelectionPath();
|
TreePath selectionPath = gTree.getSelectionPath();
|
||||||
ArchiveNode node = (ArchiveNode) selectionPath.getLastPathComponent();
|
CategoryNode node = (CategoryNode) selectionPath.getLastPathComponent();
|
||||||
|
|
||||||
Program program = plugin.getProgram();
|
Program program = plugin.getProgram();
|
||||||
DataTypeManager manager = node.getArchive().getDataTypeManager();
|
|
||||||
List<DataTypeManager> managerList = new ArrayList<DataTypeManager>();
|
|
||||||
managerList.add(manager);
|
|
||||||
ApplyFunctionDataTypesCmd cmd =
|
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();
|
PluginTool tool = plugin.getTool();
|
||||||
tool.executeBackgroundCommand(cmd, program);
|
tool.executeBackgroundCommand(cmd, program);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,8 @@
|
|||||||
<ul>
|
<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 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>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>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user