GP-4904 added method to fixup purecall defs

This commit is contained in:
ghidra007 2024-09-09 18:38:49 +00:00
parent 0348791f94
commit c3e618a2bb
3 changed files with 102 additions and 0 deletions

View File

@ -221,6 +221,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
Msg.debug(this, "Creating and Applying Class structures");
createAndApplyClassStructures();
// fix purecall vfunction definitions
fixupPurecallFunctionDefs();
updateMultiVftableLabels();
return recoveredClasses;

View File

@ -175,6 +175,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
createAndApplyClassStructures(recoveredClasses);
// fix purecall vfunction definitions
fixupPurecallFunctionDefs();
if (!isPDBLoaded) {
// create better vftable labels for multi vftable classes
updateMultiVftableLabels(recoveredClasses);

View File

@ -4524,6 +4524,102 @@ public class RecoveredClassHelper {
}
}
/**
* Method to fixup the function definitions corresponding to purecalls from vftables after
* all the child classes have been updated. This is because the function defintions for these
* abstract function definitions are generated based on the child function signatures which
* are not updated at the time the parent class structures are created.
* @throws CancelledException if cancelled
*/
protected void fixupPurecallFunctionDefs() throws CancelledException {
// do nothing if no purecall
if (purecall == null) {
return;
}
List<Address> processedVftables = new ArrayList<Address>();
// get references to purecall function to figure out which classes to process
ReferenceIterator purecallRefs =
program.getReferenceManager().getReferencesTo(purecall.getEntryPoint());
while (purecallRefs.hasNext()) {
monitor.checkCancelled();
Reference purecallRef = purecallRefs.next();
Address fromAddress = purecallRef.getFromAddress();
// get data containing the purecall reference to get the vftable structure
Data data = program.getListing().getDataContaining(fromAddress);
// skip if not a data ref
if (data == null) {
continue;
}
DataType dataType = data.getDataType();
// skip if not ref'd by a vftable
if (!dataType.getName().contains("vftable")) {
continue;
}
Address vftableAddress = data.getMinAddress();
// skip - already processed this whole table
if (processedVftables.contains(vftableAddress)) {
continue;
}
RecoveredClass recoveredClass = vftableToClassMap.get(vftableAddress);
// use the vftable structure fields to figure out which vfunctions in that vftable are
// purecalls and to also get the vfunction function definition data type
Structure vftableStructure = (Structure) dataType;
int vfunctionNumber = 1;
for (DataTypeComponent component : vftableStructure.getComponents()) {
monitor.checkCancelled();
if (component.getComment().contains("pure")) {
// get an associated child vfunction signure to update the parent's function definition
Function childVirtualFunction =
getChildVirtualFunction(recoveredClass, vfunctionNumber);
if (childVirtualFunction == null) {
Msg.debug(this, "Cannot get associated vfunction " + vfunctionNumber);
continue;
}
// get the function definition from the child vfunction
FunctionDefinitionDataType newDef =
new FunctionDefinitionDataType(childVirtualFunction, false);
// update the this param to replace class struct with void so that the
// definition is generic thiscall
ParameterDefinition[] arguments = newDef.getArguments();
PointerDataType voidPtrDt = new PointerDataType(VoidDataType.dataType);
arguments[0].setDataType(voidPtrDt);
// use it to reset the parent's associated abstract(pure) function definition
Pointer functionDefPtr = (Pointer) component.getDataType();
FunctionDefinition functionDef =
(FunctionDefinition) functionDefPtr.getDataType();
functionDef.setArguments(arguments);
functionDef.setReturnType(newDef.getReturnType());
}
vfunctionNumber++;
}
processedVftables.add(vftableAddress);
}
}
/**
* Method to get a child class virtual function at the given offset into the correct virtual function table
* @param recoveredClass the given class