diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java
index 8417cece2d..f36c713735 100644
--- a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java
+++ b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RecoveredClassHelper.java
@@ -4,9 +4,9 @@
* 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.
@@ -426,21 +426,23 @@ public class RecoveredClassHelper {
// of number of CALL instructions even if the call reg type
functionCallMap.put(instruction.getMinAddress(), calledFunction);
}
- if(instruction.getFlowOverride().equals(FlowOverride.CALL_RETURN)) {
+ if (instruction.getFlowOverride().equals(FlowOverride.CALL_RETURN)) {
Reference reference = instruction.getPrimaryReference(0);
if (reference == null) {
continue;
}
Address functionAddress = reference.getFromAddress();
- Function secondHalfOfFunction = extendedFlatAPI.getReferencedFunction(functionAddress);
- if(secondHalfOfFunction != null){
- Map
functionCallMap2 = getFunctionCallMap(secondHalfOfFunction,false);
- for(Address addr : functionCallMap2.keySet()) {
+ Function secondHalfOfFunction =
+ extendedFlatAPI.getReferencedFunction(functionAddress);
+ if (secondHalfOfFunction != null) {
+ Map functionCallMap2 =
+ getFunctionCallMap(secondHalfOfFunction, false);
+ for (Address addr : functionCallMap2.keySet()) {
monitor.checkCancelled();
functionCallMap.put(addr, functionCallMap2.get(addr));
}
}
-
+
}
}
return functionCallMap;
@@ -2264,15 +2266,14 @@ public class RecoveredClassHelper {
for (Function calledFunction : calledFunctions) {
monitor.checkCancelled();
- if (getAllConstructors().contains(calledFunction) || getAllInlinedConstructors().contains(calledFunction)) {
+ if (getAllConstructors().contains(calledFunction) ||
+ getAllInlinedConstructors().contains(calledFunction)) {
return true;
}
}
return false;
}
-
-
/**
* Method to determine if the given function calls a known denstructor or inlined destructor
@@ -2286,32 +2287,32 @@ public class RecoveredClassHelper {
for (Function calledFunction : calledFunctions) {
monitor.checkCancelled();
- if (getAllDestructors().contains(calledFunction) || getAllInlinedDestructors().contains(calledFunction)) {
+ if (getAllDestructors().contains(calledFunction) ||
+ getAllInlinedDestructors().contains(calledFunction)) {
return true;
}
}
return false;
}
-
- private boolean callsOwnFunction(RecoveredClass recoveredClass, Set calledFunctions) throws CancelledException {
-
+
+ private boolean callsOwnFunction(RecoveredClass recoveredClass, Set calledFunctions)
+ throws CancelledException {
+
for (Function calledFunction : calledFunctions) {
monitor.checkCancelled();
-
- if(recoveredClass.getConstructorOrDestructorFunctions().contains(calledFunction)) {
+
+ if (recoveredClass.getConstructorOrDestructorFunctions().contains(calledFunction)) {
return true;
}
}
return false;
}
-
-
+
private Set getCalledFunctions(Function callingFunction) throws CancelledException {
-
Set calledFunctions = new HashSet();
-
+
InstructionIterator instructions = callingFunction.getProgram()
.getListing()
.getInstructions(callingFunction.getBody(), true);
@@ -2325,11 +2326,11 @@ public class RecoveredClassHelper {
if (calledFunction == null) {
continue;
}
-
+
calledFunctions.add(calledFunction);
}
}
-
+
return calledFunctions;
}
@@ -2571,7 +2572,8 @@ public class RecoveredClassHelper {
* @param recoveredClass the given class object
* @return true if class has a vbase destructor, false if not
*/
- private boolean hasValidVbaseDestructor(RecoveredClass recoveredClass) throws CancelledException {
+ private boolean hasValidVbaseDestructor(RecoveredClass recoveredClass)
+ throws CancelledException {
Function vBaseDestructor = recoveredClass.getVBaseDestructor();
StringBuffer string = new StringBuffer();
@@ -4453,7 +4455,7 @@ public class RecoveredClassHelper {
String nameField = vfunction.getName();
FunctionDefinition functionDataType =
- new FunctionDefinitionDataType(vfunction, true);
+ new FunctionDefinitionDataType(vfunction, false);
if (!vfunction.getName().equals(functionDefName)) {
functionDataType.setName(functionDefName);
@@ -4467,24 +4469,38 @@ public class RecoveredClassHelper {
nameField = DEFAULT_VFUNCTION_PREFIX + vfunctionNumber;
- // get function sig from child class
+ // get function sig from a child class
Function childVirtualFunction =
- getChildVirtualFunction(recoveredClass, vftableAddress, vfunctionNumber);
+ getChildVirtualFunction(recoveredClass, vfunctionNumber);
+
+ // if it is null it will just use the purecall function definition since
+ // it can't find a child one to use to replace it
if (childVirtualFunction != null) {
functionDataType =
- new FunctionDefinitionDataType(childVirtualFunction, true);
+ new FunctionDefinitionDataType(childVirtualFunction, false);
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" name
- if (childFunctionSymbol.getSource() == SourceType.DEFAULT) {
- functionDataType.setName(nameField);
+ if (childFunctionSymbol.getSource() != SourceType.DEFAULT) {
+ nameField = childFunctionSymbol.getName();
}
}
+ functionDataType.setName(nameField);
comment = recoveredClass.getName() + " pure " + comment;
+ }
+ ParameterDefinition[] arguments = functionDataType.getArguments();
+
+ // if the vfunction is a thiscall then replace the classStruct* this with voidPtr
+ // so that it can be used generically for all related members of the class family
+ if (arguments.length > 0 && arguments[0].getName().equals("this")) {
+ VoidDataType voidDT = new VoidDataType();
+ PointerDataType voidPtr = new PointerDataType(voidDT);
+ ParameterDefinition parameterDefinition = arguments[0];
+ parameterDefinition.setDataType(voidPtr);
}
PointerDataType functionPointerDataType =
@@ -4515,9 +4531,12 @@ public class RecoveredClassHelper {
* @param recoveredClass the given class
* @param virtualFunctionNumber the virtual function offset into the table
* @return a child class virtual function at the given offset
+ * @throws CancelledException if cancelled
*/
- private Function getChildVirtualFunction(RecoveredClass recoveredClass, Address vftableAddress,
- int virtualFunctionNumber) {
+ private Function getChildVirtualFunction(RecoveredClass recoveredClass,
+ int virtualFunctionNumber) throws CancelledException {
+
+ Function nonThisFunction = null;
List childClasses = recoveredClass.getChildClasses();
if (childClasses.isEmpty()) {
@@ -4526,29 +4545,42 @@ public class RecoveredClassHelper {
// 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);
+ for (RecoveredClass childClass : childClasses) {
+ monitor.checkCancelled();
- List 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) {
+ List childVftableAddresses = childClass.getVftableAddresses();
+ if (childVftableAddresses.isEmpty()) {
continue;
}
- if (parentForVftable.equals(recoveredClass)) {
- List childVirtualFunctionsForGivenParent =
- childClass.getVirtualFunctions(childVftableAddress);
- if (childVirtualFunctionsForGivenParent.size() < virtualFunctionNumber) {
- 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 childVirtualFunctionsForGivenParent =
+ childClass.getVirtualFunctions(childVftableAddress);
+ if (childVirtualFunctionsForGivenParent.size() < virtualFunctionNumber) {
+ continue;
+ }
+ Function vfunction =
+ childVirtualFunctionsForGivenParent.get(virtualFunctionNumber - 1);
+ Parameter[] parameters = vfunction.getParameters();
+ if (parameters.length == 0) {
+ continue;
+ }
+ if (parameters[0].getName().equals("this")) {
+ return vfunction;
+ }
+
+ nonThisFunction = vfunction;
}
- return childVirtualFunctionsForGivenParent.get(virtualFunctionNumber - 1);
}
}
- return null;
+ return nonThisFunction; //or null if no vfunctions at all which should never happen
}
/**
@@ -5420,12 +5452,12 @@ public class RecoveredClassHelper {
// if inline, put on separate list and remove from indeterminate list
// process later
- if(callsOwnConstructorOrDestructor(recoveredClass, indeterminateFunction)) {
+ if (callsOwnConstructorOrDestructor(recoveredClass, indeterminateFunction)) {
recoveredClass.addIndeterminateInline(indeterminateFunction);
indeterminateIterator.remove();
continue;
}
-
+
if (vftableReferenceList.size() > 1) {
if (!areVftablesInSameClass(vftableReferenceList)) {
recoveredClass.addIndeterminateInline(indeterminateFunction);
@@ -5435,16 +5467,18 @@ public class RecoveredClassHelper {
}
}
}
-
- private boolean callsOwnConstructorOrDestructor(RecoveredClass recoveredClass, Function function) throws CancelledException {
-
+
+ private boolean callsOwnConstructorOrDestructor(RecoveredClass recoveredClass,
+ Function function) throws CancelledException {
+
Set calledFunctions = getCalledFunctions(function);
-
- List constructorOrDestructorFunctions = recoveredClass.getConstructorOrDestructorFunctions();
- for(Function cdFunction : constructorOrDestructorFunctions) {
+
+ List constructorOrDestructorFunctions =
+ recoveredClass.getConstructorOrDestructorFunctions();
+ for (Function cdFunction : constructorOrDestructorFunctions) {
monitor.checkCancelled();
-
- if(calledFunctions.contains(cdFunction)) {
+
+ if (calledFunctions.contains(cdFunction)) {
return true;
}
}
@@ -6133,10 +6167,10 @@ public class RecoveredClassHelper {
// weed out any that call own possible constructors and destructors
// as they will not be const/dest (possibly may be inlined one though
Set calledFunctions = getCalledFunctions(indeterminateFunction);
- if(callsOwnFunction(recoveredClass, calledFunctions)) {
+ if (callsOwnFunction(recoveredClass, calledFunctions)) {
continue;
}
-
+
// first try identifying using known constructors and destructors
boolean callsKnownConstructor = callsKnownConstructor(calledFunctions);
boolean callsKnownDestructor = callsKnownDestructor(calledFunctions);
@@ -6164,7 +6198,7 @@ public class RecoveredClassHelper {
// Next try identifying constructors using decompiler return type
DataType decompilerReturnType =
decompilerUtils.getDecompilerReturnType(indeterminateFunction);
-
+
if (decompilerReturnType != null) {
String returnDataName = decompilerReturnType.getDisplayName();
@@ -7622,7 +7656,7 @@ public class RecoveredClassHelper {
return null;
}
- FunctionSignature listingFunctionSignature = vfunction.getSignature(true);
+ FunctionSignature listingFunctionSignature = vfunction.getSignature(false);
FunctionDefinition componentFunctionDefinition =
getComponentFunctionDefinition(structureComponent);
@@ -8195,7 +8229,7 @@ public class RecoveredClassHelper {
vfunction = vfunction.getThunkedFunction(true);
}
- FunctionSignature listingFunctionSignature = vfunction.getSignature(true);
+ FunctionSignature listingFunctionSignature = vfunction.getSignature(false);
if (listingFunctionSignature.getName().contains("purecall")) {
return null;