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 new file mode 100644 index 0000000000..b86307c98d --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DataTypeNamingUtil.java @@ -0,0 +1,76 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.util; + +import ghidra.program.model.data.*; +import ghidra.util.InvalidNameException; + +public class DataTypeNamingUtil { + + private DataTypeNamingUtil() { + // no construct + } + + /** + * Generate a simple mangled function definition name and apply it to the specified functionDefinition. + * @param functionDefinition function definition whose name should be set + * @param namePrefix prefix to be applied to generated name. An underscore will separate this prefix from the + * remainder of the mangled name. If null specified a prefix of "_function" will be used. + * @return name applied to functionDefinition + * @throws IllegalArgumentException if generated name contains unsupported characters + */ + public static String setMangledAnonymousFunctionName( + FunctionDefinitionDataType functionDefinition, String namePrefix) + throws IllegalArgumentException { + + DataType returnType = functionDefinition.getReturnType(); + ParameterDefinition[] parameters = functionDefinition.getArguments(); + + if (namePrefix == null) { + namePrefix = "_function"; + } + StringBuilder sb = new StringBuilder(namePrefix); + + GenericCallingConvention convention = functionDefinition.getGenericCallingConvention(); + if (convention != null && convention != GenericCallingConvention.unknown) { + sb.append(convention.getDeclarationName()); + } + sb.append("_"); + + sb.append(mangleDTName(returnType.getName())); + for (ParameterDefinition p : parameters) { + sb.append("_").append(mangleDTName(p.getDataType().getName())); + } + + if (functionDefinition.hasVarArgs()) { + sb.append("_").append("varargs"); + } + + String name = sb.toString(); + try { + functionDefinition.setName(name); + } + catch (InvalidNameException e) { + throw new IllegalArgumentException(e); + } + return name; + } + + private static String mangleDTName(String s) { + return s.replaceAll(" ", "_").replaceAll("\\*", "ptr"); + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeImporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeImporter.java index 4f0e9c74e2..42636e1507 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeImporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeImporter.java @@ -22,6 +22,7 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import ghidra.app.plugin.core.datamgr.util.DataTypeUtils; +import ghidra.app.util.DataTypeNamingUtil; import ghidra.app.util.bin.format.dwarf4.*; import ghidra.app.util.bin.format.dwarf4.encoding.*; import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionException; @@ -271,12 +272,6 @@ public class DWARFDataTypeImporter { foundThisParam |= DWARFUtil.isThisParam(childDIEA); } - if (dni.isAnon() && mangleAnonFuncNames) { - dni = dni.replaceName( - dni.getName() + "_" + getMangledFuncDefName(returnType.dataType, params), - dni.getOriginalName()); - } - FunctionDefinitionDataType funcDef = new FunctionDefinitionDataType(dni.getParentCP(), dni.getName(), dataTypeManager); funcDef.setReturnType(returnType.dataType); @@ -290,6 +285,12 @@ public class DWARFDataTypeImporter { funcDef.setGenericCallingConvention(GenericCallingConvention.thiscall); } + if (dni.isAnon() && mangleAnonFuncNames) { + String mangledName = + DataTypeNamingUtil.setMangledAnonymousFunctionName(funcDef, dni.getName()); + dni = dni.replaceName(mangledName, dni.getOriginalName()); + } + for (int i = 0; i < funcDef.getArguments().length; i++) { ParameterDefinition origPD = params.get(i); ParameterDefinition newPD = funcDef.getArguments()[i]; @@ -343,27 +344,27 @@ public class DWARFDataTypeImporter { return refdDT; } - /** - * Mash parameter datatype names together to make a mangling suffix to append to - * a function def name. - *

- * @param returnTypeDT - * @param parameters - * @return - */ - private String getMangledFuncDefName(DataType returnTypeDT, - List parameters) { - StringBuilder sb = new StringBuilder(); - sb.append(mangleDTName(returnTypeDT.getName())); - for (ParameterDefinition p : parameters) { - sb.append("_").append(mangleDTName(p.getDataType().getName())); - } - return sb.toString(); - } - - private String mangleDTName(String s) { - return s.replaceAll(" ", "_").replaceAll("\\*", "ptr"); - } +// /** +// * Mash parameter datatype names together to make a mangling suffix to append to +// * a function def name. +// *

+// * @param returnTypeDT +// * @param parameters +// * @return +// */ +// private String getMangledFuncDefName(DataType returnTypeDT, +// List parameters) { +// StringBuilder sb = new StringBuilder(); +// sb.append(mangleDTName(returnTypeDT.getName())); +// for (ParameterDefinition p : parameters) { +// sb.append("_").append(mangleDTName(p.getDataType().getName())); +// } +// return sb.toString(); +// } +// +// private String mangleDTName(String s) { +// return s.replaceAll(" ", "_").replaceAll("\\*", "ptr"); +// } /** * Creates a Ghidra {@link Enum} datatype. diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbCategories.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbCategories.java index a889f76e62..5c39a05139 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbCategories.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbCategories.java @@ -38,7 +38,7 @@ public class PdbCategories { private CategoryPath baseModuleTypedefsCategory; private List typedefCategories = new ArrayList<>(); - private int anonymousFunctionCount; +// private int anonymousFunctionCount; //============================================================================================== // NOTE: a TODO could be to add optional GUID and AGE values. This could be as sub-categories @@ -59,7 +59,7 @@ public class PdbCategories { setTypedefCategoryPaths(moduleNames); anonymousFunctionsCategory = new CategoryPath(pdbRootCategory, "!_anon_funcs_"); - anonymousFunctionCount = 0; +// anonymousFunctionCount = 0; anonymousTypesCategory = new CategoryPath(pdbRootCategory, "!_anon_types_"); } @@ -190,22 +190,22 @@ public class PdbCategories { return anonymousTypesCategory; } - /** - * Returns the name of what should be the next Anonymous Function (based on the count of - * the number of anonymous functions) so that there is a unique name for the function. - * @return the name for the next anonymous function. - */ - public String getNextAnonymousFunctionName() { - return String.format("_func_%08X", anonymousFunctionCount); - } - - /** - * Updates the count of the anonymous functions. This is a separate call from - * {@link #getNextAnonymousFunctionName()} because the count should only be updated after - * the previous anonymous function has been successfully created/stored. - */ - public void incrementNextAnonymousFunctionName() { - anonymousFunctionCount++; - } +// /** +// * Returns the name of what should be the next Anonymous Function (based on the count of +// * the number of anonymous functions) so that there is a unique name for the function. +// * @return the name for the next anonymous function. +// */ +// public String getNextAnonymousFunctionName() { +// return String.format("_func_%08X", anonymousFunctionCount); +// } +// +// /** +// * Updates the count of the anonymous functions. This is a separate call from +// * {@link #getNextAnonymousFunctionName()} because the count should only be updated after +// * the previous anonymous function has been successfully created/stored. +// */ +// public void incrementNextAnonymousFunctionName() { +// anonymousFunctionCount++; +// } } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java index e5e7c459ab..7c2af2d121 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java @@ -15,6 +15,7 @@ */ package ghidra.app.util.pdb.pdbapplicator; +import ghidra.app.util.DataTypeNamingUtil; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber; import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType; @@ -42,12 +43,12 @@ public abstract class AbstractFunctionTypeApplier extends MsTypeApplier { */ public AbstractFunctionTypeApplier(PdbApplicator applicator, AbstractMsType msType) { super(applicator, msType); - String funcName = applicator.getNextAnonymousFunctionName(); +// String funcName = applicator.getNextAnonymousFunctionName(); functionDefinition = new FunctionDefinitionDataType( - applicator.getAnonymousFunctionsCategory(), funcName, applicator.getDataTypeManager()); + applicator.getAnonymousFunctionsCategory(), "_func", applicator.getDataTypeManager()); // Updating before trying to apply... if applyFunction fails, then this name will go // unused for the most part, but we also will not get a conflict on the name. - applicator.incrementNextAnonymousFunctionName(); +// applicator.incrementNextAnonymousFunctionName(); dataType = functionDefinition; } @@ -191,7 +192,13 @@ public abstract class AbstractFunctionTypeApplier extends MsTypeApplier { argsListApplier.applyTo(this); } setCallingConvention(applicator, callingConvention, hasThisPointer); + DataTypeNamingUtil.setMangledAnonymousFunctionName(functionDefinition, "_func"); setApplied(); + +// resolvedDataType = applicator.resolveHighUse(dataType); +// if (resolvedDataType != null) { +// resolved = true; +// } } private boolean setReturnType() { diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java index c6da819197..87c22a4edf 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java @@ -516,23 +516,23 @@ public class PdbApplicator { return categoryUtils.getAnonymousTypesCategory(); } - /** - * Returns the name of what should be the next Anonymous Function (based on the count of - * the number of anonymous functions) so that there is a unique name for the function. - * @return the name for the next anonymous function. - */ - String getNextAnonymousFunctionName() { - return categoryUtils.getNextAnonymousFunctionName(); - } +// /** +// * Returns the name of what should be the next Anonymous Function (based on the count of +// * the number of anonymous functions) so that there is a unique name for the function. +// * @return the name for the next anonymous function. +// */ +// String getNextAnonymousFunctionName() { +// return categoryUtils.getNextAnonymousFunctionName(); +// } - /** - * Updates the count of the anonymous functions. This is a separate call from - * {@link #getNextAnonymousFunctionName()} because the count should only be updated after - * the previous anonymous function has been successfully created/stored. - */ - void incrementNextAnonymousFunctionName() { - categoryUtils.incrementNextAnonymousFunctionName(); - } +// /** +// * Updates the count of the anonymous functions. This is a separate call from +// * {@link #getNextAnonymousFunctionName()} because the count should only be updated after +// * the previous anonymous function has been successfully created/stored. +// */ +// void incrementNextAnonymousFunctionName() { +// categoryUtils.incrementNextAnonymousFunctionName(); +// } private PdbCategories setPdbCatogoryUtils(String pdbFilename) throws CancelledException, PdbException { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java index ca9ed9afb5..1ea8ae4003 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java @@ -124,6 +124,9 @@ public interface DataType { * Sets the name of the dataType * @param name the new name for this dataType. * @throws InvalidNameException if the given name does not form a valid name. + * @throws DuplicateNameException if name change on stored {@link DataType} + * is a duplciate of another datatype within the same category (only applies to + * DB stored {@link DataType}). */ public void setName(String name) throws InvalidNameException, DuplicateNameException; @@ -132,7 +135,9 @@ public interface DataType { * @param path the new category path. * @param name the new name * @throws InvalidNameException if the name is invalid - * @throws DuplicateNameException if a dataType already exists with that name and + * @throws DuplicateNameException if name change on stored {@link DataType} + * is a duplciate of another datatype within the same category (only applies to + * DB stored {@link DataType}). */ public void setNameAndCategory(CategoryPath path, String name) throws InvalidNameException, DuplicateNameException; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java index 7d97369f6b..2b664e8a50 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java @@ -37,7 +37,7 @@ public final class DataUtilities { * @return true if name is valid, else false */ public static boolean isValidDataTypeName(String name) { - if (name == null) { + if (name == null || name.length() == 0) { return false; }