GP-301 PDB - use consistent anonymous function naming with DWARF. Helps

to reduce datatype conflicts.
This commit is contained in:
ghidra1 2020-10-26 19:25:57 -04:00
parent 0086c4c77a
commit f7e219b96a
7 changed files with 156 additions and 67 deletions

View file

@ -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");
}
}

View file

@ -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.
* <p>
* @param returnTypeDT
* @param parameters
* @return
*/
private String getMangledFuncDefName(DataType returnTypeDT,
List<ParameterDefinition> 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.
// * <p>
// * @param returnTypeDT
// * @param parameters
// * @return
// */
// private String getMangledFuncDefName(DataType returnTypeDT,
// List<ParameterDefinition> 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.

View file

@ -38,7 +38,7 @@ public class PdbCategories {
private CategoryPath baseModuleTypedefsCategory;
private List<CategoryPath> 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++;
// }
}

View file

@ -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() {

View file

@ -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 {

View file

@ -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;

View file

@ -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;
}