diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionData.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionData.java index a66dc66688..4054cc13af 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionData.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionData.java @@ -218,7 +218,7 @@ class FunctionData extends FunctionDataView { } VariableStorage[] paramStorage = - effectiveCallingConvention.getStorageLocations(getProgram(), dataTypes, true); + effectiveCallingConvention.getStorageLocations(getProgram(), dataTypes, true, hasVarArgs); returnInfo.setStorage(paramStorage[0]); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java index fef08a80ca..2793543343 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PrototypeModel.java @@ -398,6 +398,30 @@ public class PrototypeModel { */ public VariableStorage[] getStorageLocations(Program program, DataType[] dataTypes, boolean addAutoParams) { + return getStorageLocations(program, dataTypes, addAutoParams, false); + } + + /** + * Calculate input and output storage locations given a function prototype, + * with optional variable-argument support. + *

+ * This overload additionally sets {@link PrototypePieces#firstVarArgSlot} when + * {@code isVarArgs} is true, enabling {@code VarargsFilter}-based calling-convention + * rules (e.g. {@code } in a .cspec) to be applied correctly. + * + * @param program is the Program + * @param dataTypes return/parameter datatypes (first element is always the return datatype, + * i.e., minimum array length is 1) + * @param addAutoParams true if auto-parameter storage locations can be generated + * @param isVarArgs true if the function takes variable arguments; when true, all + * data-types supplied in {@code dataTypes} are treated as non-optional and the first + * vararg slot is set to immediately follow the last supplied parameter + * @return dynamic storage locations ordered by ordinal where first element corresponds to + * return storage. The returned array may also include additional auto-parameter storage + * locations. + */ + public VariableStorage[] getStorageLocations(Program program, DataType[] dataTypes, + boolean addAutoParams, boolean isVarArgs) { DataType injectedThis = null; if (addAutoParams && hasThis) { @@ -406,6 +430,10 @@ public class PrototypeModel { injectedThis = new PointerDataType(program.getDataTypeManager()); } PrototypePieces proto = new PrototypePieces(this, dataTypes, injectedThis); + if (isVarArgs) { + // All supplied parameters are non-optional; varargs begin immediately after them. + proto.firstVarArgSlot = proto.intypes.size(); + } ArrayList res = new ArrayList<>(); assignParameterStorage(proto, program.getDataTypeManager(), res, addAutoParams);