mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-301 PDB - use consistent anonymous function naming with DWARF. Helps
to reduce datatype conflicts.
This commit is contained in:
parent
0086c4c77a
commit
f7e219b96a
7 changed files with 156 additions and 67 deletions
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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++;
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue