diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java index ff7473569b..d7ea18c3ee 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java @@ -19,6 +19,7 @@ import java.util.*; import ghidra.program.model.address.*; import ghidra.program.model.data.*; +import ghidra.program.model.lang.PrototypeModel; import ghidra.program.model.lang.Register; import ghidra.program.model.listing.*; import ghidra.program.model.listing.Function.FunctionUpdateType; @@ -39,6 +40,38 @@ public class HighFunctionDBUtil { public static final String AUTO_CAT = "/auto_proto"; // Category for auto generated prototypes + /** + * Return the appropriate model name for committing to the database with the given HighFunction. + * Generally this just returns the model name attached to the HighFunction, but if the "unknown" + * model is associated with the function, or if the model doesn't exist, the decompiler + * was using the "default" model internally, so this is the more appropriate model to commit. + * Its possible for this routine to return null, if the architecture has no default model. + * @param highFunction is the given HighFunction + * @return the model name to commit + */ + private static String getPrototypeModelForCommit(HighFunction highFunction) { + FunctionPrototype prototype = highFunction.getFunctionPrototype(); + String modelName = (prototype != null) ? prototype.getModelName() : null; + if (modelName != null) { + if (modelName.equals(Function.UNKNOWN_CALLING_CONVENTION_STRING)) { + modelName = null; + } + else { + if (null == highFunction.getCompilerSpec().getCallingConvention(modelName)) { + modelName = null; + } + } + } + if (modelName == null) { + // Currently the decompiler uses the default convention to model an unknown convention + PrototypeModel model = highFunction.getCompilerSpec().getDefaultCallingConvention(); + if (model != null) { + modelName = model.getName(); + } + } + return modelName; + } + /** * Commit the decompiler's version of the function return data-type to the database. * The decompiler's version of the prototype model is committed as well @@ -51,7 +84,7 @@ public class HighFunctionDBUtil { // Change calling convention if needed Function function = highFunction.getFunction(); String convention = function.getCallingConventionName(); - String modelName = highFunction.getFunctionPrototype().getModelName(); + String modelName = getPrototypeModelForCommit(highFunction); if (modelName != null && !modelName.equals(convention)) { function.setCallingConvention(modelName); } @@ -84,8 +117,7 @@ public class HighFunctionDBUtil { List params = getParameters(highFunction, useDataTypes); - FunctionPrototype functionPrototype = highFunction.getFunctionPrototype(); - String modelName = (functionPrototype != null) ? functionPrototype.getModelName() : null; + String modelName = getPrototypeModelForCommit(highFunction); commitParamsToDatabase(function, modelName, params, highFunction.getFunctionPrototype().isVarArg(), true, source); }