diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java index e9586fa3ac..490ac106ee 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java @@ -145,15 +145,6 @@ public class RustDemanglerAnalyzer extends AbstractDemanglerAnalyzer { try { if (demangled instanceof DemangledFunction defunc) { defunc.applyTo(program, address, options, monitor); - Function func = program.getFunctionManager().getFunctionAt(address); - if (func != null) { - // if has no return type and no parameters, don't trust that it is void and unlock - // the signature so the decompiler can figure it out - if (defunc.getReturnType() == null && defunc.getParameters().size() == 0) { - func.setSignatureSource(SourceType.DEFAULT); - } - return; - } } } catch (Exception e) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemangler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemangler.java index 81df013870..9aae1ed45b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemangler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemangler.java @@ -16,6 +16,7 @@ package ghidra.app.plugin.core.analysis.rust.demangler; import ghidra.app.util.demangler.*; +import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.listing.Program; /** @@ -68,8 +69,9 @@ public class RustDemangler implements Demangler { RustDemanglerParser parser = new RustDemanglerParser(); DemangledObject demangledObject = parser.parse(mangled, demangled); - if (options.applyCallingConvention() && demangledObject instanceof DemangledFunction) { - ((DemangledFunction) demangledObject).setCallingConvention("rustcall"); + if (options.applyCallingConvention() && + demangledObject instanceof DemangledFunction demangledFunction) { + demangledFunction.setCallingConvention(CompilerSpec.CALLING_CONVENTION_rustcall); } return demangledObject; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerLegacy.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerLegacy.java index 64646bc1a1..946d8eb4a8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerLegacy.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerLegacy.java @@ -72,6 +72,9 @@ public class RustDemanglerLegacy { element = element.replace("$LP$", "("); element = element.replace("$RP$", ")"); element = element.replace("$C$", ","); + + // Ghidra uses :: between namespace names + element = element.replace("..", "::"); int k = 0; while (k < element.length()) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerParser.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerParser.java index 461ca0d528..ba85e0d4b9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerParser.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemanglerParser.java @@ -22,6 +22,7 @@ import java.util.stream.Collectors; import generic.json.Json; import ghidra.app.util.SymbolPathParser; import ghidra.app.util.demangler.*; +import ghidra.program.model.symbol.SourceType; /** Parses a demangled rust string */ public class RustDemanglerParser { @@ -67,10 +68,12 @@ public class RustDemanglerParser { private DemangledObject parseNext(String demangled) { String nameString = removeBadSpaces(demangled).trim(); - DemangledFunction variable = + DemangledFunction demangledFunction = new DemangledFunction(mangledSource, demangledSource, (String) null); - setNameAndNamespace(variable, nameString); - return variable; + setNameAndNamespace(demangledFunction, nameString); + // Restrict to applying name, namespace and calling-convention + demangledFunction.setSignatureSourceType(SourceType.DEFAULT); + return demangledFunction; } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/DataTypeNamingUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DataTypeNamingUtil.java index 83ecf27cbe..dc7f9bfa61 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/DataTypeNamingUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DataTypeNamingUtil.java @@ -36,8 +36,7 @@ public class DataTypeNamingUtil { * @throws IllegalArgumentException if generated name contains unsupported characters */ public static String setMangledAnonymousFunctionName( - FunctionDefinitionDataType functionDefinition) - throws IllegalArgumentException { + FunctionDefinitionDataType functionDefinition) throws IllegalArgumentException { DataType returnType = functionDefinition.getReturnType(); ParameterDefinition[] parameters = functionDefinition.getArguments(); @@ -49,7 +48,7 @@ public class DataTypeNamingUtil { } String convention = functionDefinition.getCallingConventionName(); - if (convention != null && !Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(convention)) { + if (!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(convention)) { sb.append("_").append(convention); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java index 9edf8b22e7..87de4e07af 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java @@ -289,12 +289,12 @@ public class ToolTipUtils { } buffy.append(friendlyEncodeHTML(function.getReturnType().getName())); buffy.append(HTML_SPACE); - + String callingConvention = function.getCallingConventionName(); if (callingConvention.equals(Function.DEFAULT_CALLING_CONVENTION_STRING)) { callingConvention = function.getCallingConvention().getName(); } - if (!callingConvention.equals(Function.UNKNOWN_CALLING_CONVENTION_STRING)) { + if (!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConvention)) { String ccHtml = friendlyEncodeHTML(callingConvention); if (function.hasUnknownCallingConventionName()) { ccHtml = colorString(Color.RED, ccHtml); @@ -302,7 +302,7 @@ public class ToolTipUtils { buffy.append(ccHtml); buffy.append(HTML_SPACE); } - + String functionName = StringUtilities.trimMiddle(function.getName(), LINE_LENGTH); buffy.append(colorString(FunctionColors.NAME, friendlyEncodeHTML(functionName))); buffy.append(HTML_SPACE).append("("); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java index a514ffb900..9343ab55a0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java @@ -24,9 +24,11 @@ import ghidra.app.cmd.function.*; import ghidra.app.util.NamespaceUtils; import ghidra.app.util.PseudoDisassembler; import ghidra.program.database.data.DataTypeUtilities; +import ghidra.program.database.data.ProgramBasedDataTypeManagerDB; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.data.*; +import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.PrototypeModel; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; @@ -55,6 +57,7 @@ public class DemangledFunction extends DemangledObject { protected List parameters = new ArrayList<>(); protected DemangledTemplate template; protected boolean isOverloadedOperator = false; + protected SourceType signatureSourceType = SourceType.ANALYSIS; /** Special constructor where it has a templated type before the parameter list */ private String templatedConstructorType; @@ -67,11 +70,43 @@ public class DemangledFunction extends DemangledObject { private boolean isTypeCast; private String throwAttribute; + /** + * Create a {@link DemangledFunction} instance which is marked with a + * signature {@link SourceType} of {@link SourceType#ANALYSIS} which will be used + * when function signatures are applied to a program. This source type may be changed + * if needed using {@link #setSignatureSourceType(SourceType)}. + * The function name and namespace is always applied using a symbol source + * of {@link SourceType#ANALYSIS}. + * @param mangled original mangled symbol name + * @param originalDemangled demangled function signature generally used when generating comments + * @param name demangled function name + */ public DemangledFunction(String mangled, String originalDemangled, String name) { super(mangled, originalDemangled); setName(name); } + /** + * Set signature {@link SourceType} of {@link SourceType#ANALYSIS} which will be used + * when function signatures are applied to a program. Specifying {@link SourceType#DEFAULT} + * will prevent function return and parameters from being applied but will still apply + * calling convention name if specified. + * @param signatureSourceType signature source type + */ + public void setSignatureSourceType(SourceType signatureSourceType) { + this.signatureSourceType = signatureSourceType; + } + + /** + * Get the signature source type which is used when applying the function signature + * to a program. A value of {@link SourceType#DEFAULT} indicates that + * function return and parameters should not be applied. + * @return signature source type + */ + public SourceType getSignatureSourceType() { + return signatureSourceType; + } + /** * Sets the function return type. * @param returnType the function return type @@ -433,6 +468,22 @@ public class DemangledFunction extends DemangledObject { return true; } + boolean hasCallingConvention = !CompilerSpec.isUnknownCallingConvention(callingConvention); + if (hasCallingConvention) { + // Ensure that calling convention name exists and can be used + ProgramBasedDataTypeManagerDB dtm = + (ProgramBasedDataTypeManagerDB) program.getDataTypeManager(); + dtm.getCallingConventionID(callingConvention, false); + } + + if (signatureSourceType == SourceType.DEFAULT) { + // Only apply calling convention if specified with DEFAULT source + if (hasCallingConvention) { + function.setCallingConvention(callingConvention); + } + return true; + } + Structure classStructure = maybeUpdateCallingConventionAndCreateClass(program, function, options); @@ -454,7 +505,7 @@ public class DemangledFunction extends DemangledObject { } ApplyFunctionSignatureCmd cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(), - signature, SourceType.IMPORTED, true, false, DataTypeConflictHandler.DEFAULT_HANDLER, + signature, signatureSourceType, true, false, DataTypeConflictHandler.DEFAULT_HANDLER, FunctionRenameOption.RENAME_IF_DEFAULT); cmd.applyTo(program); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java index f0951ab1a4..0534c05a6c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java @@ -363,6 +363,18 @@ public abstract class DemangledObject implements Demangled { this.errorMessage = message; } + /** + * Apply this demangled object detail to the specified program. + *
+ * NOTE: An open Program transaction must be established prior to invoking this method. + * + * @param program program to which demangled data should be applied. + * @param address address which corresponds to this demangled object + * @param options options which control how demangled data is applied + * @param monitor task monitor + * @return true if successfully applied, else false + * @throws Exception if an error occurs during the apply operation + */ public boolean applyTo(Program program, Address address, DemanglerOptions options, TaskMonitor monitor) throws Exception { return applyPlateCommentOnly(program, address); diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/analyzers/RustDemanglerLegacyTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/analyzers/RustDemanglerLegacyTest.java index 97dfdd4d8c..b401dc4202 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/analyzers/RustDemanglerLegacyTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/analyzers/RustDemanglerLegacyTest.java @@ -22,8 +22,12 @@ import org.junit.Test; import ghidra.app.plugin.core.analysis.rust.demangler.RustDemangler; import ghidra.app.util.demangler.DemangledException; import ghidra.app.util.demangler.DemangledObject; +import ghidra.program.model.lang.CompilerSpec; public class RustDemanglerLegacyTest { + + private static final String RUSTCALL = CompilerSpec.CALLING_CONVENTION_rustcall; + private static String[] symbols = { "_ZN43_$LT$char$u20$as$u20$core..fmt..Display$GT$3fmt17h31c4c24bbd08aa24E", "_ZN4core6option13expect_failed17h09b982639336e7eaE", @@ -32,13 +36,13 @@ public class RustDemanglerLegacyTest { "_ZN5alloc5alloc18handle_alloc_error8rt_error17h4b79f8a717741b7cE", "_ZN3std6thread7current17h20e47a880e55afd5E", }; - private static String[] names = { "rustcall _::fmt(void)", - "rustcall core::option::expect_failed(void)", - "rustcall core::fmt::Formatter::debug_lower_hex(void)", - "rustcall std::path::Components::as_path(void)", - "rustcall alloc::alloc::handle_alloc_error::rt_error(void)", - "rustcall std::thread::current(void)", - "rustcall gimli::read::abbrev::Attributes::new(void)" }; + private static String[] names = { RUSTCALL + " _::fmt(void)", + RUSTCALL + " core::option::expect_failed(void)", + RUSTCALL + " core::fmt::Formatter::debug_lower_hex(void)", + RUSTCALL + " std::path::Components::as_path(void)", + RUSTCALL + " alloc::alloc::handle_alloc_error::rt_error(void)", + RUSTCALL + " std::thread::current(void)", + RUSTCALL + " gimli::read::abbrev::Attributes::new(void)" }; @Test public void demangle() { diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerCallConventionAnalyzer.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerCallConventionAnalyzer.java index 011d39266d..e70046a3d3 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerCallConventionAnalyzer.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerCallConventionAnalyzer.java @@ -27,6 +27,7 @@ import ghidra.app.util.importer.MessageLog; import ghidra.framework.options.Options; import ghidra.program.model.address.*; import ghidra.program.model.data.*; +import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.SourceType; @@ -206,8 +207,7 @@ public class DecompilerCallConventionAnalyzer extends AbstractAnalyzer { // must be an unknown signature String callingConventionName = function.getCallingConventionName(); - - if (!callingConventionName.equals(Function.UNKNOWN_CALLING_CONVENTION_STRING)) { + if (!CompilerSpec.isUnknownCallingConvention(callingConventionName)) { continue; } diff --git a/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java b/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java index f6edcedf57..c1a6bc3f16 100644 --- a/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java +++ b/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java @@ -19,6 +19,7 @@ import java.util.Iterator; import ghidra.app.util.demangler.*; import ghidra.program.model.lang.CompilerSpec; +import ghidra.program.model.symbol.SourceType; import mdemangler.datatype.MDDataType; import mdemangler.datatype.MDVarArgsType; import mdemangler.datatype.complex.*; @@ -216,6 +217,7 @@ public class MDMangGhidra extends MDMang { else { DemangledFunction function = new DemangledFunction(mangledSource, demangledSource, objectCPP.getName()); + function.setSignatureSourceType(SourceType.IMPORTED); function.setNamespace(processNamespace(objectCPP.getQualification())); resultObject = function; objectResult = processFunction((MDFunctionInfo) typeinfo, function); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/stringable/FunctionSignatureStringable.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/stringable/FunctionSignatureStringable.java index 453e5e504c..4f0ba0b416 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/stringable/FunctionSignatureStringable.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/stringable/FunctionSignatureStringable.java @@ -15,68 +15,24 @@ */ package ghidra.feature.vt.api.stringable; -import static ghidra.feature.vt.gui.util.VTOptionDefines.CALLING_CONVENTION; -import static ghidra.feature.vt.gui.util.VTOptionDefines.CALL_FIXUP; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_CALLING_CONVENTION; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_CALL_FIXUP; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_FUNCTION_RETURN_TYPE; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_FUNCTION_SIGNATURE; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_HIGHEST_NAME_PRIORITY; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_INLINE; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_NO_RETURN; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_COMMENTS; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_DATA_TYPES; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_NAMES; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_NAMES_REPLACE_IF_SAME_PRIORITY; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_VAR_ARGS; -import static ghidra.feature.vt.gui.util.VTOptionDefines.FUNCTION_RETURN_TYPE; -import static ghidra.feature.vt.gui.util.VTOptionDefines.INLINE; -import static ghidra.feature.vt.gui.util.VTOptionDefines.NO_RETURN; -import static ghidra.feature.vt.gui.util.VTOptionDefines.PARAMETER_COMMENTS; -import static ghidra.feature.vt.gui.util.VTOptionDefines.PARAMETER_NAMES_REPLACE_IF_SAME_PRIORITY; -import static ghidra.feature.vt.gui.util.VTOptionDefines.VAR_ARGS; +import static ghidra.feature.vt.gui.util.VTOptionDefines.*; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; +import java.util.*; import ghidra.feature.vt.api.util.Stringable; import ghidra.feature.vt.api.util.VersionTrackingApplyException; import ghidra.feature.vt.gui.util.VTMatchApplyChoices; -import ghidra.feature.vt.gui.util.VTMatchApplyChoices.CallingConventionChoices; -import ghidra.feature.vt.gui.util.VTMatchApplyChoices.CommentChoices; -import ghidra.feature.vt.gui.util.VTMatchApplyChoices.FunctionSignatureChoices; -import ghidra.feature.vt.gui.util.VTMatchApplyChoices.HighestSourcePriorityChoices; -import ghidra.feature.vt.gui.util.VTMatchApplyChoices.ParameterDataTypeChoices; -import ghidra.feature.vt.gui.util.VTMatchApplyChoices.ReplaceChoices; +import ghidra.feature.vt.gui.util.VTMatchApplyChoices.*; import ghidra.feature.vt.gui.util.VTOptionDefines; import ghidra.framework.options.ToolOptions; import ghidra.program.database.data.DataTypeUtilities; -import ghidra.program.model.data.DataType; -import ghidra.program.model.data.DataTypeManager; -import ghidra.program.model.data.Pointer; -import ghidra.program.model.data.PointerDataType; -import ghidra.program.model.data.Undefined; -import ghidra.program.model.lang.CompilerSpec; -import ghidra.program.model.lang.Language; -import ghidra.program.model.lang.PrototypeModel; -import ghidra.program.model.listing.Function; +import ghidra.program.model.data.*; +import ghidra.program.model.lang.*; +import ghidra.program.model.listing.*; import ghidra.program.model.listing.Function.FunctionUpdateType; -import ghidra.program.model.listing.FunctionSignature; -import ghidra.program.model.listing.Parameter; -import ghidra.program.model.listing.ParameterImpl; -import ghidra.program.model.listing.Program; -import ghidra.program.model.listing.ReturnParameterImpl; -import ghidra.program.model.listing.VariableStorage; -import ghidra.program.model.symbol.SourceType; -import ghidra.program.model.symbol.SymbolTable; -import ghidra.program.model.symbol.SymbolUtilities; +import ghidra.program.model.symbol.*; import ghidra.program.util.FunctionUtility; -import ghidra.util.Msg; -import ghidra.util.StringUtilities; -import ghidra.util.SystemUtilities; +import ghidra.util.*; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.InvalidInputException; @@ -544,9 +500,8 @@ public class FunctionSignatureStringable extends Stringable { public boolean applyFunctionSignature(Function toFunction, ToolOptions markupOptions, boolean forceApply) throws VersionTrackingApplyException { - VTMatchApplyChoices.FunctionSignatureChoices functionSignatureChoice = - markupOptions.getEnum(VTOptionDefines.FUNCTION_SIGNATURE, - DEFAULT_OPTION_FOR_FUNCTION_SIGNATURE); + VTMatchApplyChoices.FunctionSignatureChoices functionSignatureChoice = markupOptions + .getEnum(VTOptionDefines.FUNCTION_SIGNATURE, DEFAULT_OPTION_FOR_FUNCTION_SIGNATURE); int toParamCount = toFunction.getParameterCount(); @@ -586,10 +541,11 @@ public class FunctionSignatureStringable extends Stringable { List newParams = getParameters(toFunction, markupOptions, forceApply, useCustomStorage); - toFunction.updateFunction(conventionName, returnParam, newParams, - useCustomStorage ? FunctionUpdateType.CUSTOM_STORAGE - : FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, - true, signatureSource); + toFunction + .updateFunction(conventionName, returnParam, newParams, + useCustomStorage ? FunctionUpdateType.CUSTOM_STORAGE + : FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, + true, signatureSource); if (forceApply) { // must force signatureSource if precedence has been lowered // TODO: Should any manual change in function signature force source to be USER_DEFINED instead ?? @@ -723,8 +679,8 @@ public class FunctionSignatureStringable extends Stringable { } private String getCallingConvention(Function toFunction, ToolOptions markupOptions) { - boolean isFromUnknownCallingConvention = ((callingConventionName == null) || - callingConventionName.equals(Function.UNKNOWN_CALLING_CONVENTION_STRING)); + boolean isFromUnknownCallingConvention = + CompilerSpec.isUnknownCallingConvention(callingConventionName); CallingConventionChoices callingConventionChoice = markupOptions.getEnum(CALLING_CONVENTION, DEFAULT_OPTION_FOR_CALLING_CONVENTION); String toCallingConventionName = toFunction.getCallingConventionName(); @@ -854,8 +810,8 @@ public class FunctionSignatureStringable extends Stringable { throws VersionTrackingApplyException { // See what options the user has specified when applying parameter names. - VTMatchApplyChoices.SourcePriorityChoices parameterNamesChoice = markupOptions.getEnum( - VTOptionDefines.PARAMETER_NAMES, DEFAULT_OPTION_FOR_PARAMETER_NAMES); + VTMatchApplyChoices.SourcePriorityChoices parameterNamesChoice = markupOptions + .getEnum(VTOptionDefines.PARAMETER_NAMES, DEFAULT_OPTION_FOR_PARAMETER_NAMES); VTMatchApplyChoices.HighestSourcePriorityChoices highestPriorityChoice = markupOptions.getEnum(VTOptionDefines.HIGHEST_NAME_PRIORITY, DEFAULT_OPTION_FOR_HIGHEST_NAME_PRIORITY); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CallingConventionDBAdapterV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CallingConventionDBAdapterV0.java index 8815377062..61759bcb06 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CallingConventionDBAdapterV0.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CallingConventionDBAdapterV0.java @@ -67,8 +67,8 @@ class CallingConventionDBAdapterV0 extends CallingConventionDBAdapter { String tableName = tablePrefix + CALLING_CONVENTION_TABLE_NAME; if (create) { // No additional indexed fields. - callingConventionTable = handle.createTable(tableName, - V0_CALLING_CONVENTION_SCHEMA, new int[] {}); + callingConventionTable = + handle.createTable(tableName, V0_CALLING_CONVENTION_SCHEMA, new int[] {}); } else { callingConventionTable = handle.getTable(tableName); @@ -138,7 +138,7 @@ class CallingConventionDBAdapterV0 extends CallingConventionDBAdapter { @Override byte getCallingConventionId(String name, Consumer conventionAdded) throws IOException { - if (name == null || name.equals(CompilerSpec.CALLING_CONVENTION_unknown)) { + if (CompilerSpec.isUnknownCallingConvention(name)) { return UNKNOWN_CALLING_CONVENTION_ID; } else if (name.equals(CompilerSpec.CALLING_CONVENTION_default)) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java index 6268716c45..cae9c38c34 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java @@ -4008,7 +4008,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { public byte getCallingConventionID(String name, boolean restrictive) throws InvalidInputException, IOException { - if (name == null || CompilerSpec.CALLING_CONVENTION_unknown.equals(name)) { + if (CompilerSpec.isUnknownCallingConvention(name)) { return UNKNOWN_CALLING_CONVENTION_ID; } if (CompilerSpec.CALLING_CONVENTION_default.equals(name)) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FunctionDefinitionDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FunctionDefinitionDataType.java index 7a407f70f3..99cfc04ccc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FunctionDefinitionDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FunctionDefinitionDataType.java @@ -178,8 +178,7 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct @Override public void setCallingConvention(String conventionName) throws InvalidInputException { - if (conventionName == null || - CompilerSpec.CALLING_CONVENTION_unknown.equals(conventionName)) { + if (CompilerSpec.isUnknownCallingConvention(conventionName)) { this.callingConventionName = CompilerSpec.CALLING_CONVENTION_unknown; return; } @@ -365,8 +364,7 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct if ((signature.getName().equals(this.name)) && (compareComment(signature)) && (DataTypeUtilities.isSameOrEquivalentDataType(signature.getReturnType(), this.returnType)) && - (hasVarArgs == signature.hasVarArgs()) && - (hasNoReturn == signature.hasNoReturn()) && + (hasVarArgs == signature.hasVarArgs()) && (hasNoReturn == signature.hasNoReturn()) && callingConventionName.equals(signature.getCallingConventionName())) { ParameterDefinition[] args = signature.getArguments(); if (args.length == this.params.length) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java index a4ab9dffec..89bb059f43 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java @@ -1089,7 +1089,7 @@ public class BasicCompilerSpec implements CompilerSpec { @Override public PrototypeModel matchConvention(String conventionName) { - if (conventionName == null || CALLING_CONVENTION_unknown.equals(conventionName) || + if (CompilerSpec.isUnknownCallingConvention(conventionName) || CALLING_CONVENTION_default.equals(conventionName)) { return defaultModel; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java index 061f6057a4..ce9f62732d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/CompilerSpec.java @@ -18,6 +18,8 @@ package ghidra.program.model.lang; import java.io.IOException; import java.util.Set; +import org.apache.commons.lang3.StringUtils; + import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.data.DataOrganization; @@ -48,6 +50,7 @@ public interface CompilerSpec { public final static String CALLING_CONVENTION_stdcall = "__stdcall"; public final static String CALLING_CONVENTION_fastcall = "__fastcall"; public final static String CALLING_CONVENTION_vectorcall = "__vectorcall"; + public final static String CALLING_CONVENTION_rustcall = "__rustcall"; /** * Labels for PrototypeModels that are used by default for various analysis/evaluation @@ -59,6 +62,19 @@ public interface CompilerSpec { EVAL_CALLED // A PrototypeModel used to evaluate a "called" function } + /** + * Determine if the specified calling convention name is treated as the unknown calling + * convention (blank or {code "unknown"}). Other unrecognized names will return false. + * This static method does not assume any specific compiler specification. + * + * @param callingConventionName calling convention name or null + * @return true if specified name is blank or {code "unknown"} + */ + public static boolean isUnknownCallingConvention(String callingConventionName) { + return StringUtils.isBlank(callingConventionName) || + CompilerSpec.CALLING_CONVENTION_unknown.equals(callingConventionName); + } + /** * Get the Language this compiler spec is based on. Note that * compiler specs may be reused across multiple languages in the diff --git a/Ghidra/Processors/x86/data/extensions/rust/unix/cc.xml b/Ghidra/Processors/x86/data/extensions/rust/unix/cc.xml index bbb7608cea..9c7ff08500 100644 --- a/Ghidra/Processors/x86/data/extensions/rust/unix/cc.xml +++ b/Ghidra/Processors/x86/data/extensions/rust/unix/cc.xml @@ -1,4 +1,4 @@ - +