GP-3747 PR-5644 reworked updateFunctionDefinition part of PR.

This commit is contained in:
ghidra007 2023-08-21 19:47:55 +00:00
parent 152b6349b0
commit 45eb6eb187

View file

@ -16,7 +16,17 @@
//DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS. //DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS.
package classrecovery; package classrecovery;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd; import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
@ -30,21 +40,78 @@ import ghidra.app.util.NamespaceUtils;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.data.DataTypeUtilities; import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.flatapi.FlatProgramAPI;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.address.AddressOutOfBoundsException;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.AddressRangeIterator;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.address.GlobalNamespace;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.Category;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeComponent;
import ghidra.program.model.data.DataTypeConflictHandler;
import ghidra.program.model.data.DataTypeDependencyException;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.FunctionDefinition;
import ghidra.program.model.data.FunctionDefinitionDataType;
import ghidra.program.model.data.NoisyStructureBuilder;
import ghidra.program.model.data.ParameterDefinition;
import ghidra.program.model.data.Pointer;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.Structure;
import ghidra.program.model.data.StructureDataType;
import ghidra.program.model.data.Undefined1DataType;
import ghidra.program.model.data.Undefined4DataType;
import ghidra.program.model.data.Undefined8DataType;
import ghidra.program.model.data.VoidDataType;
import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.Bookmark;
import ghidra.program.model.listing.BookmarkManager;
import ghidra.program.model.listing.BookmarkType;
import ghidra.program.model.listing.CircularDependencyException;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Function.FunctionUpdateType; import ghidra.program.model.listing.Function.FunctionUpdateType;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.listing.FunctionSignature;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.InstructionIterator;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Parameter;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ReturnParameterImpl;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.HighFunction;
import ghidra.program.model.symbol.*; import ghidra.program.model.pcode.HighVariable;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.PcodeOpAST;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.Namespace;
import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolIterator;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.model.symbol.SymbolType;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramMemoryUtil; import ghidra.program.util.ProgramMemoryUtil;
import ghidra.util.InvalidNameException; import ghidra.util.InvalidNameException;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.bytesearch.*; import ghidra.util.bytesearch.GenericByteSequencePattern;
import ghidra.util.bytesearch.GenericMatchAction;
import ghidra.util.bytesearch.Match;
import ghidra.util.bytesearch.MemoryBytePatternSearcher;
import ghidra.util.datastruct.ListAccumulator; import ghidra.util.datastruct.ListAccumulator;
import ghidra.util.exception.*; import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class RecoveredClassHelper { public class RecoveredClassHelper {
@ -7828,9 +7895,21 @@ public class RecoveredClassHelper {
ParameterDefinition[] currentArgs = functionDefinition.getArguments(); ParameterDefinition[] currentArgs = functionDefinition.getArguments();
ParameterDefinition[] changedArgs = newFunctionDefinition.getArguments(); ParameterDefinition[] changedArgs = newFunctionDefinition.getArguments();
// only update if there are differences // only update if same number of params and there are differences
if (!currentArgs.equals(changedArgs)) { // if different number then user must decide whether to update the definition
functionDefinition.setArguments(changedArgs); if (currentArgs.length > 0 && currentArgs.length == changedArgs.length) {
// keep the original function definition's this param if there is one hard coded
// if only the this is different then don't update changed flag
if (currentArgs[0].getName().equals("this")) {
changedArgs[0] = currentArgs[0];
}
// if other than hard-coded this is different then change
// to use to changedArgs
if (!areEqualFunctionArgs(currentArgs, changedArgs)) {
functionDefinition.setArguments(changedArgs);
changed = true;
}
} }
if (!functionDefinition.getReturnType().equals(newFunctionDefinition.getReturnType())) { if (!functionDefinition.getReturnType().equals(newFunctionDefinition.getReturnType())) {
@ -7844,6 +7923,44 @@ public class RecoveredClassHelper {
} }
private boolean areEqualFunctionArgs(ParameterDefinition[] currentArgs,
ParameterDefinition[] changedArgs) {
// not equals if diff num or arguments
if (currentArgs.length != changedArgs.length) {
return false;
}
// equals if both have no args
if (currentArgs.length == 0) {
return true;
}
// not equals if any args are not equal
for (int i = 0; i < currentArgs.length; i++) {
if (!areEqualArgs(currentArgs[i], changedArgs[i])) {
return false;
}
}
// equals if all args are equal
return true;
}
private boolean areEqualArgs(ParameterDefinition def1, ParameterDefinition def2) {
if (!def1.isEquivalent(def2)) {
return false;
}
if (!def1.getName().equals(def2.getName())) {
return false;
}
return true;
}
public List<Structure> getClassStructures() throws CancelledException { public List<Structure> getClassStructures() throws CancelledException {
Category category = program.getDataTypeManager().getCategory(classDataTypesCategoryPath); Category category = program.getDataTypeManager().getCategory(classDataTypesCategoryPath);