diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java index 1d7b25124d6..b4aaaaafb08 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java @@ -16,7 +16,17 @@ //DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS. 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 ghidra.app.cmd.function.ApplyFunctionSignatureCmd; @@ -30,21 +40,78 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.program.database.data.DataTypeUtilities; import ghidra.program.flatapi.FlatProgramAPI; -import ghidra.program.model.address.*; -import ghidra.program.model.data.*; +import ghidra.program.model.address.Address; +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.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.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.pcode.*; -import ghidra.program.model.symbol.*; +import ghidra.program.model.pcode.HighFunction; +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.ProgramMemoryUtil; import ghidra.util.InvalidNameException; 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.exception.*; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.DuplicateNameException; +import ghidra.util.exception.InvalidInputException; import ghidra.util.task.TaskMonitor; public class RecoveredClassHelper { @@ -7828,9 +7895,21 @@ private FunctionDefinition updateFunctionDefinition(FunctionDefinition functionD ParameterDefinition[] currentArgs = functionDefinition.getArguments(); ParameterDefinition[] changedArgs = newFunctionDefinition.getArguments(); - // only update if there are differences - if (!currentArgs.equals(changedArgs)) { - functionDefinition.setArguments(changedArgs); + // only update if same number of params and there are differences + // if different number then user must decide whether to update the definition + 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())) { @@ -7844,6 +7923,44 @@ private FunctionDefinition updateFunctionDefinition(FunctionDefinition functionD } + 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 getClassStructures() throws CancelledException { Category category = program.getDataTypeManager().getCategory(classDataTypesCategoryPath);