GP-1311 In RecoverClassesFromRTTIScript support, removed the 'this *' from vfunction definitions to enable generic class assignment and allowed purecall vfunction pointer to be replaced with pointers to correct class vfunction definition.

This commit is contained in:
ghidra007 2021-11-09 15:02:03 +00:00
parent 766ff7f72e
commit a4349ba443

View file

@ -4529,14 +4529,40 @@ public class RecoveredClassUtils {
// of using the function name of "purecall" and prepend "pure" to the comment so // of using the function name of "purecall" and prepend "pure" to the comment so
// they know it is pure virtual function, ie not actually implemented in the parent class // they know it is pure virtual function, ie not actually implemented in the parent class
String nameField = vfunction.getName(); String nameField = vfunction.getName();
FunctionDefinition functionDataType =
new FunctionDefinitionDataType(vfunction, true);
functionDataType.setReturnType(vfunction.getReturnType());
// if the function is a purecall need to create the function definition using
// the equivalent child virtual function signature
if (nameField.contains("purecall")) { if (nameField.contains("purecall")) {
nameField = DEFAULT_VFUNCTION_PREFIX + vfunctionNumber; nameField = DEFAULT_VFUNCTION_PREFIX + vfunctionNumber;
// get function sig from child class
Function childVirtualFunction =
getChildVirtualFunction(recoveredClass, vftableAddress, vfunctionNumber);
if (childVirtualFunction != null) {
functionDataType =
new FunctionDefinitionDataType(childVirtualFunction, true);
functionDataType.setReturnType(childVirtualFunction.getReturnType());
Symbol childFunctionSymbol =
symbolTable.getPrimarySymbol(childVirtualFunction.getEntryPoint());
// if the child function has a default name, rename the function definition
// data type to the "vfunction<vfunctionNumber>" name
if (childFunctionSymbol.getSource() == SourceType.DEFAULT) {
functionDataType.setName(nameField);
}
}
comment = recoveredClass.getName() + " pure " + comment; comment = recoveredClass.getName() + " pure " + comment;
} }
PointerDataType functionPointerDataType = PointerDataType functionPointerDataType =
createFunctionSignaturePointerDataType(vfunction, classPath); createFunctionSignaturePointerDataType(functionDataType, classPath);
vftableStruct.add(functionPointerDataType, nameField, vftableStruct.add(functionPointerDataType, nameField,
classCommentPrefix + " " + comment); classCommentPrefix + " " + comment);
@ -4558,6 +4584,47 @@ public class RecoveredClassUtils {
} }
} }
/**
* Method to get a child class virtual function at the given offset into the correct virtual function table
* @param recoveredClass the given class
* @param virtualFunctionNumber the virtual function offset into the table
* @return a child class virtual function at the given offset
*/
private Function getChildVirtualFunction(RecoveredClass recoveredClass, Address vftableAddress,
int virtualFunctionNumber) {
List<RecoveredClass> childClasses = recoveredClass.getChildClasses();
if (childClasses.isEmpty()) {
return null;
}
// The child functions should all have the same function signature so just get any one of them
// if for some reason they don't, still have to pick one and let user decide how to update
RecoveredClass childClass = childClasses.get(0);
List<Address> childVftableAddresses = childClass.getVftableAddresses();
if (childVftableAddresses.isEmpty()) {
return null;
}
// get the correct child vftable for the given parent class
for (Address childVftableAddress : childVftableAddresses) {
RecoveredClass parentForVftable = childClass.getVftableBaseClass(childVftableAddress);
if (parentForVftable == null) {
continue;
}
if (parentForVftable.equals(recoveredClass)) {
List<Function> childVirtualFunctionsForGivenParent =
childClass.getVirtualFunctions(childVftableAddress);
if (childVirtualFunctionsForGivenParent.size() < virtualFunctionNumber) {
return null;
}
return childVirtualFunctionsForGivenParent.get(virtualFunctionNumber - 1);
}
}
return null;
}
/** /**
* Method to give default names to the vfunctions in the given vftable if they don't have a name already. If they are a clone or deleting destructor name them accordingly. * Method to give default names to the vfunctions in the given vftable if they don't have a name already. If they are a clone or deleting destructor name them accordingly.
* @param recoveredClass the given class * @param recoveredClass the given class
@ -4764,14 +4831,22 @@ public class RecoveredClassUtils {
classHierarchyIterator = classHierarchy.iterator(); classHierarchyIterator = classHierarchy.iterator();
} }
FunctionDefinition functionDataType = new FunctionDefinitionDataType(vfunction, true);
functionDataType.setReturnType(vfunction.getReturnType());
while (classHierarchyIterator.hasNext()) { while (classHierarchyIterator.hasNext()) {
monitor.checkCanceled(); monitor.checkCanceled();
RecoveredClass currentClass = classHierarchyIterator.next(); RecoveredClass currentClass = classHierarchyIterator.next();
List<Function> virtualFunctions = currentClass.getAllVirtualFunctions();
if (virtualFunctions.contains(vfunction)) { CategoryPath currentClassPath = currentClass.getClassPath();
classPath = currentClass.getClassPath(); DataType existingDataType =
dataTypeManager.getDataType(currentClassPath, functionDataType.getName());
if (existingDataType != null) {
return currentClassPath;
} }
} }
return classPath; return classPath;
@ -4779,40 +4854,33 @@ public class RecoveredClassUtils {
/** /**
* *
* @param vfunction the given function * @param functionDefDataType the function definition
* @param classPath the given data type manager classPath * @param classPath the given data type manager classPath
* @return pointer to function signature data type * @return pointer to function signature data type
* @throws DuplicateNameException if try to create same symbol name already in namespace * @throws DuplicateNameException if try to create same symbol name already in namespace
*/ */
private PointerDataType createFunctionSignaturePointerDataType(Function vfunction, private PointerDataType createFunctionSignaturePointerDataType(
CategoryPath classPath) throws DuplicateNameException { FunctionDefinition functionDefDataType, CategoryPath classPath)
throws DuplicateNameException {
FunctionDefinition functionDataType = (FunctionDefinitionDataType) vfunction.getSignature();
DataType returnType = vfunction.getReturnType();
functionDataType.setReturnType(returnType);
// If this data type doesn't exist in this folder make a new one
// otherwise use the existing one
DataType existingDataType = DataType existingDataType =
dataTypeManager.getDataType(classPath, functionDataType.getName()); dataTypeManager.getDataType(classPath, functionDefDataType.getName());
PointerDataType functionPointerDataType; PointerDataType functionPointerDataType;
// If the given function definition doesn't exist in this folder make a new one and
// make a pointer to it
if (existingDataType == null) { if (existingDataType == null) {
functionDataType.setCategoryPath(classPath); functionDefDataType.setCategoryPath(classPath);
functionDataType = (FunctionDefinition) dataTypeManager.addDataType(functionDataType, functionPointerDataType = new PointerDataType(functionDefDataType, dataTypeManager);
DataTypeConflictHandler.DEFAULT_HANDLER);
functionPointerDataType = new PointerDataType(functionDataType);
} }
// otherwise return a pointer to the existing one
else { else {
functionPointerDataType = new PointerDataType(existingDataType); functionPointerDataType = new PointerDataType(existingDataType);
} }
return functionPointerDataType; return functionPointerDataType;
} }
/** /**
* Method to add precomment inside functions containing inlined constructors at approximate * Method to add precomment inside functions containing inlined constructors at approximate
* address of start of inlined function * address of start of inlined function
@ -6868,7 +6936,7 @@ public class RecoveredClassUtils {
vfunction = thunkedFunction; vfunction = thunkedFunction;
} }
FunctionSignature listingFunctionSignature = vfunction.getSignature(); FunctionSignature listingFunctionSignature = vfunction.getSignature(true);
DataTypeComponent structureComponent = vfunctionStructure.getComponent(vfunctionIndex); DataTypeComponent structureComponent = vfunctionStructure.getComponent(vfunctionIndex);
@ -7584,7 +7652,7 @@ public class RecoveredClassUtils {
vfunction = vfunction.getThunkedFunction(true); vfunction = vfunction.getThunkedFunction(true);
} }
FunctionSignature listingFunctionSignature = vfunction.getSignature(); FunctionSignature listingFunctionSignature = vfunction.getSignature(true);
DataType componentDataType = structureComponent.getDataType(); DataType componentDataType = structureComponent.getDataType();
if (!(componentDataType instanceof Pointer)) { if (!(componentDataType instanceof Pointer)) {