GP-1663 The RecoverClassesForRTTIScript was updated to improve function definition creation for the multi-inheritance and single virtual inheritance cases.

This commit is contained in:
ghidra007 2022-01-11 18:51:06 +00:00
parent ba2eb53110
commit 0c1c7d1acf

View file

@ -4665,9 +4665,21 @@ public class RecoveredClassHelper {
replaceClassStructure(vfunction, recoveredClass.getName(), classStruct); replaceClassStructure(vfunction, recoveredClass.getName(), classStruct);
} }
String forClassSuffix = getForClassSuffix(vftableStructureName);
String functionDefName = vfunction.getName();
int indexOfSuffix = functionDefName.indexOf(forClassSuffix);
// if vfunction name has the "for_parent" suffix, strip it off for the function definition name
if (indexOfSuffix > 0) {
functionDefName = functionDefName.substring(0, indexOfSuffix);
}
// get the classPath of highest level parent with vfAddress in their vftable // get the classPath of highest level parent with vfAddress in their vftable
classPath = classPath =
getCategoryPathForFunctionSignature(vfunction, recoveredClass, vftableAddress); getCategoryPathForFunctionSignature(vfunction, functionDefName, recoveredClass,
vftableAddress);
Symbol vfunctionSymbol = symbolTable.getPrimarySymbol(vfunction.getEntryPoint()); Symbol vfunctionSymbol = symbolTable.getPrimarySymbol(vfunction.getEntryPoint());
Namespace parentNamespace = vfunctionSymbol.getParentNamespace(); Namespace parentNamespace = vfunctionSymbol.getParentNamespace();
@ -4695,12 +4707,14 @@ public class RecoveredClassHelper {
// Create comment to indicate it is a virtual function and which number in the table // Create comment to indicate it is a virtual function and which number in the table
String comment = VFUNCTION_COMMENT + vfunctionNumber; String comment = VFUNCTION_COMMENT + vfunctionNumber;
// add suffix for multi classes to distinguish which vftable it is for // add comment suffix for multi classes to distinguish which vftable it is for
String commentSuffix = getForClassSuffix(vftableStructureName);
if (!commentSuffix.isEmpty()) { if (!forClassSuffix.isEmpty()) {
int index = commentSuffix.indexOf("for_");
int index = forClassSuffix.indexOf("for_");
String commentSuffix = "";
if (index > 0) { if (index > 0) {
commentSuffix = " for parent class " + commentSuffix.substring(index + 4); commentSuffix = " for parent class " + forClassSuffix.substring(index + 4);
} }
comment = comment + commentSuffix; comment = comment + commentSuffix;
} }
@ -4713,6 +4727,10 @@ public class RecoveredClassHelper {
FunctionDefinition functionDataType = FunctionDefinition functionDataType =
new FunctionDefinitionDataType(vfunction, true); new FunctionDefinitionDataType(vfunction, true);
if (!vfunction.getName().equals(functionDefName)) {
functionDataType.setName(functionDefName);
}
functionDataType.setReturnType(vfunction.getReturnType()); functionDataType.setReturnType(vfunction.getReturnType());
// if the function is a purecall need to create the function definition using // if the function is a purecall need to create the function definition using
@ -4966,13 +4984,16 @@ public class RecoveredClassHelper {
/** /**
* Method to retrieve the class path of the highest ancestor with matching vfunction in its vftable * Method to retrieve the class path of the highest ancestor with matching vfunction in its vftable
* @param vfunction the given virtual function * @param vfunction the given virtual function
* @param functionDefName the given function definition name
* @param recoveredClass the given class * @param recoveredClass the given class
* @param vftableAddress the given virtual function table from the given class * @param vftableAddress the given virtual function table from the given class
* @return the class path for the highest ancestor with matching virtual function in its vftable * @return the class path for the highest ancestor with matching virtual function in its vftable
* @throws CancelledException when cancelled * @throws CancelledException when cancelled
* @throws InvalidNameException if functionDefName is invalid name
*/ */
CategoryPath getCategoryPathForFunctionSignature(Function vfunction, CategoryPath getCategoryPathForFunctionSignature(Function vfunction, String functionDefName,
RecoveredClass recoveredClass, Address vftableAddress) throws CancelledException { RecoveredClass recoveredClass, Address vftableAddress)
throws CancelledException, InvalidNameException {
// if class has no parent, return its own classPath // if class has no parent, return its own classPath
CategoryPath classPath = recoveredClass.getClassPath(); CategoryPath classPath = recoveredClass.getClassPath();
@ -4987,33 +5008,42 @@ public class RecoveredClassHelper {
return classPath; return classPath;
} }
Iterator<RecoveredClass> classHierarchyIterator; // if the class has multiple inheritance or single virtual inheritance get the parent from
if (recoveredClass.hasSingleInheritance()) { // the "_for_<parentName>" in the given vftable
List<RecoveredClass> classHierarchy = recoveredClass.getClassHierarchy(); if (recoveredClass.hasMultipleInheritance() ||
classHierarchyIterator = classHierarchy.listIterator(1); (recoveredClass.hasSingleInheritance() && recoveredClass.inheritsVirtualAncestor())) {
}
else {
// get the parent that goes with the given vftableAddress
// if there is no parent associated with the vftable then return the current
// class's class path
RecoveredClass parentClass = recoveredClass.getVftableBaseClass(vftableAddress); RecoveredClass parentClass = recoveredClass.getVftableBaseClass(vftableAddress);
// if can't recover the parent from the vftable just return the class's class path
if (parentClass == null) { if (parentClass == null) {
return classPath; return classPath;
} }
// get the class hierarchy for the parent // else return the parent associated with the vftableAddress
List<RecoveredClass> classHierarchy = return parentClass.getClassPath();
recoveredClass.getClassHierarchyMap().get(parentClass);
if (classHierarchy == null) {
return classPath;
}
classHierarchyIterator = classHierarchy.iterator();
} }
FunctionDefinition functionDataType = new FunctionDefinitionDataType(vfunction, true); // else class has normal single inheritance so just search for the matching function definition
// in one of the class's ancestors and return the ancestor class it is found in or if not found,
// return the current class
List<RecoveredClass> classHierarchy = recoveredClass.getClassHierarchy();
functionDataType.setReturnType(vfunction.getReturnType()); // classHierarchy list always contains current class in first item so skip that one
// to search only the ancestors
Iterator<RecoveredClass> classHierarchyIterator = classHierarchy.listIterator(1);
// TODO: eventually use the function definition to do an equivalence check amongst
// possible same-name vfunctions to make sure getting the correct one
// in this case need to update the below check in dtMan to look through the .conflicts
// FunctionDefinition functionDataType = new FunctionDefinitionDataType(vfunction, true);
//
// functionDataType.setReturnType(vfunction.getReturnType());
// try {
// functionDataType.setName(functionDefName);
// }
// catch (DuplicateNameException e) {
// // ignore -- don't rename if it is already the same name
// }
while (classHierarchyIterator.hasNext()) { while (classHierarchyIterator.hasNext()) {
monitor.checkCanceled(); monitor.checkCanceled();
@ -5022,7 +5052,8 @@ public class RecoveredClassHelper {
CategoryPath currentClassPath = currentClass.getClassPath(); CategoryPath currentClassPath = currentClass.getClassPath();
DataType existingDataType = DataType existingDataType =
dataTypeManager.getDataType(currentClassPath, functionDataType.getName()); dataTypeManager.getDataType(currentClassPath, functionDefName);
if (existingDataType != null) { if (existingDataType != null) {
return currentClassPath; return currentClassPath;
} }