GP-1581 Recover classes script deleting destructor and clone discovery improvements.

This commit is contained in:
ghidra007 2022-04-14 19:28:49 +00:00
parent a9c928bb14
commit 22d4c2069b
5 changed files with 969 additions and 728 deletions

View file

@ -36,7 +36,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
final int defaultPointerSize; final int defaultPointerSize;
ExtendedFlatProgramAPI(Program program, TaskMonitor taskMonitor) { public ExtendedFlatProgramAPI(Program program, TaskMonitor taskMonitor) {
super(program, taskMonitor); super(program, taskMonitor);
defaultPointerSize = program.getDefaultPointerSize(); defaultPointerSize = program.getDefaultPointerSize();
@ -668,30 +668,31 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
* Get the nth called function from calling function * Get the nth called function from calling function
* @param callingFunction The calling function * @param callingFunction The calling function
* @param callIndex the called function index (ie 1 = first called function) * @param callIndex the called function index (ie 1 = first called function)
* @param getThunkedFunction if true get the thunked function, if false get the thunk itself, if
* there is a thunk
* @return the nth called function in calling function * @return the nth called function in calling function
* @throws CancelledException if cancelled * @throws CancelledException if cancelled
*/ */
public Function getCalledFunctionByCallOrder(Function callingFunction, int callIndex) public Function getCalledFunctionByCallOrder(Function callingFunction, int callIndex,
throws CancelledException { boolean getThunkedFunction) throws CancelledException {
List<ReferenceAddressPair> orderedReferenceAddressPairsFromCallingFunction = int callNumber = 0;
getOrderedReferenceAddressPairsFromCallingFunction(callingFunction); InstructionIterator instructions = callingFunction.getProgram()
if (callIndex > orderedReferenceAddressPairsFromCallingFunction.size()) { .getListing()
return null; .getInstructions(callingFunction.getBody(), true);
while (instructions.hasNext() && callNumber < callIndex) {
monitor.checkCanceled();
Instruction instruction = instructions.next();
if (instruction.getFlowType().isCall()) {
callNumber++;
if (callNumber == callIndex) {
Function referencedFunction =
getReferencedFunction(instruction.getMinAddress(), getThunkedFunction);
return referencedFunction;
}
}
} }
return null;
ReferenceAddressPair referenceAddressPair =
orderedReferenceAddressPairsFromCallingFunction.get(callIndex - 1);
Address calledFunctionAddress = referenceAddressPair.getDestination();
Function calledFunction = getFunctionAt(calledFunctionAddress);
if (calledFunction == null) {
return null;
}
if (calledFunction.isThunk()) {
calledFunction = calledFunction.getThunkedFunction(true);
}
return calledFunction;
} }
/** /**
@ -885,11 +886,8 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
while (referenceIterator.hasNext()) { while (referenceIterator.hasNext()) {
monitor.checkCanceled(); monitor.checkCanceled();
Address referenceAddress = referenceIterator.next(); Address referenceAddress = referenceIterator.next();
Address referencedAddress = getSingleReferencedAddress(referenceAddress);
if (referencedAddress == null) { Function function = getReferencedFunction(referenceAddress, true);
continue;
}
Function function = getFunctionAt(referencedAddress);
// skip the ones that reference a vftable // skip the ones that reference a vftable
if (function != null) { if (function != null) {
@ -905,30 +903,43 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
* @param address the given address * @param address the given address
* @param getThunkedFunction if true and referenced function is a thunk, get the thunked function * @param getThunkedFunction if true and referenced function is a thunk, get the thunked function
* @return the referenced function or null if no function is referenced * @return the referenced function or null if no function is referenced
* @throws CancelledException if cancelled
*/ */
public Function getReferencedFunction(Address address, boolean getThunkedFunction) { public Function getReferencedFunction(Address address, boolean getThunkedFunction)
throws CancelledException {
Address referencedAddress = getSingleReferencedAddress(address); Reference[] referencesFrom = getReferencesFrom(address);
if (referencedAddress == null) { if (referencesFrom.length == 0) {
return null; return null;
} }
Function function = getFunctionAt(referencedAddress); for (Reference referenceFrom : referencesFrom) {
if (function == null) { monitor.checkCanceled();
return null;
}
if (!getThunkedFunction) { Address referencedAddress = referenceFrom.getToAddress();
if (referencedAddress == null) {
continue;
}
Function function = getFunctionAt(referencedAddress);
if (function == null) {
continue;
}
if (!getThunkedFunction) {
return function;
}
if (function.isThunk()) {
function = function.getThunkedFunction(true);
}
return function; return function;
} }
if (function.isThunk()) { return null;
function = function.getThunkedFunction(true);
}
return function;
} }

View file

@ -258,7 +258,6 @@ public class RTTIClassRecoverer extends RecoveredClassHelper {
memberFunctionsToProcess.addAll(recoveredClass.getConstructorList()); memberFunctionsToProcess.addAll(recoveredClass.getConstructorList());
memberFunctionsToProcess.addAll(recoveredClass.getDestructorList()); memberFunctionsToProcess.addAll(recoveredClass.getDestructorList());
memberFunctionsToProcess.addAll(recoveredClass.getIndeterminateList()); memberFunctionsToProcess.addAll(recoveredClass.getIndeterminateList());
memberFunctionsToProcess.addAll(recoveredClass.getInlinedConstructorList()); memberFunctionsToProcess.addAll(recoveredClass.getInlinedConstructorList());
Iterator<Function> memberFunctionIterator = memberFunctionsToProcess.iterator(); Iterator<Function> memberFunctionIterator = memberFunctionsToProcess.iterator();

View file

@ -1077,20 +1077,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
return true; return true;
} }
private Data createVftableArray(Address vftableAddress, int numFunctionPointers)
throws Exception {
api.clearListing(vftableAddress,
vftableAddress.add((numFunctionPointers * defaultPointerSize - 1)));
DataType pointerDataType = dataTypeManager.getPointer(null);
ArrayDataType vftableArrayDataType =
new ArrayDataType(pointerDataType, numFunctionPointers, defaultPointerSize);
Data vftableArrayData = api.createData(vftableAddress, vftableArrayDataType);
return vftableArrayData;
}
/** /**
* Method to check for a valid vtable at the given address * Method to check for a valid vtable at the given address
* @param vtableAddress the given address * @param vtableAddress the given address

View file

@ -132,6 +132,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
return recoveredClasses; return recoveredClasses;
} }
//TODO: decide whether to update to only include possible cds not all functions that
// have ref to vftable
// if decide to be more restrictive then need to move the method that weeds out inlines and
// from the class cd lists
createCalledFunctionMap(recoveredClasses); createCalledFunctionMap(recoveredClasses);
// figure out class hierarchies using either RTTI or vftable refs // figure out class hierarchies using either RTTI or vftable refs
@ -154,9 +158,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
// otherwise figure everything out from scratch // otherwise figure everything out from scratch
else { else {
monitor.setMessage("Figuring out class method types"); monitor.setMessage("Figuring out class method types");
// println(
// "Figuring out class method types (constructor, destructor, inline constructor, " +
// "inline destructor, deleting destructor, clone) ...");
processConstructorAndDestructors(recoveredClasses); processConstructorAndDestructors(recoveredClasses);
} }
@ -171,7 +172,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
// using all the information found above, create the class structures, add the constructor, // using all the information found above, create the class structures, add the constructor,
// destructor, vfunctions to class which finds the appropriate class structure and assigns // destructor, vfunctions to class which finds the appropriate class structure and assigns
// to "this" param // to "this" param
//println("Creating class data types and applying class structures...");
monitor.setMessage("Creating class data types and applying class structures"); monitor.setMessage("Creating class data types and applying class structures");
figureOutClassDataMembers(recoveredClasses); figureOutClassDataMembers(recoveredClasses);
@ -184,7 +184,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
if (!isPDBLoaded) { if (!isPDBLoaded) {
// create better vftable labels for multi vftable classes // create better vftable labels for multi vftable classes
updateMultiVftableLabels(recoveredClasses); updateMultiVftableLabels(recoveredClasses);
//println("Removing erroneous FID namespaces and corresponding class data types");
removeEmptyClassesAndStructures(); removeEmptyClassesAndStructures();
} }
@ -463,10 +462,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
num1 + "," + num2 + "," + num3 + "," + num4 + ")", num1 + "," + num2 + "," + num3 + "," + num4 + ")",
classNamespace, SourceType.ANALYSIS); classNamespace, SourceType.ANALYSIS);
} }
// else {
// println(
// "Failed to create a baseClassDescArray structure at " + address.toString());
// }
} }
} }
} }
@ -553,8 +548,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
classHierarchyStructure = createClassHierarchyStructure(classHierarchyDescriptorAddress); classHierarchyStructure = createClassHierarchyStructure(classHierarchyDescriptorAddress);
if (classHierarchyStructure == null) { if (classHierarchyStructure == null) {
// println("Failed to create a classHierarchyDescriptor structure at " +
// classHierarchyDescriptorAddress.toString());
symbolTable.removeSymbolSpecial(classHierarchySymbol); symbolTable.removeSymbolSpecial(classHierarchySymbol);
return null; return null;
} }
@ -729,12 +722,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
for (Reference refTo : referencesTo) { for (Reference refTo : referencesTo) {
Address vftableMetaPointer = refTo.getFromAddress(); Address vftableMetaPointer = refTo.getFromAddress();
if (vftableMetaPointer == null) { if (vftableMetaPointer == null) {
//println("can't retrieve meta address");
continue; continue;
} }
Address vftableAddress = vftableMetaPointer.add(defaultPointerSize); Address vftableAddress = vftableMetaPointer.add(defaultPointerSize);
if (vftableAddress == null) { if (vftableAddress == null) {
//println("can't retrieve vftable address");
continue; continue;
} }
@ -905,8 +896,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
} }
} }
List<Symbol> vftableSymbolsInNamespace = List<Symbol> vftableSymbolsInNamespace = getClassVftableSymbols(classNamespace);
getVftablesInNamespace(vftableSymbols, classNamespace);
//if there are no vftables in this class then create a new class object and make it //if there are no vftables in this class then create a new class object and make it
// non-vftable class // non-vftable class
@ -1204,7 +1194,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
} }
else if (symbols.size() > 1) { else if (symbols.size() > 1) {
//TODO: throw exception? //TODO: throw exception?
//println(recoveredClass.getName() + " has more than one base class array");
} }
return classHierarchy; return classHierarchy;
} }
@ -1292,7 +1281,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
private void processConstructorAndDestructors(List<RecoveredClass> recoveredClasses) private void processConstructorAndDestructors(List<RecoveredClass> recoveredClasses)
throws CancelledException, InvalidInputException, DuplicateNameException, Exception { throws CancelledException, InvalidInputException, DuplicateNameException, Exception {
// find deleting destructors using various mechanisms // update the global lists and class lists to narrow the cd lists
trimConstructorDestructorLists(recoveredClasses);
// find deleting destructors
findDeletingDestructors(recoveredClasses); findDeletingDestructors(recoveredClasses);
// use atexit param list to find more destructors // use atexit param list to find more destructors
@ -1316,9 +1308,8 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
// ones that could not be determined in earlier stages // ones that could not be determined in earlier stages
processRemainingIndeterminateConstructorsAndDestructors(recoveredClasses); processRemainingIndeterminateConstructorsAndDestructors(recoveredClasses);
// use the known constructors and known vfunctions to figure out // use the known constructors and known vfunctions to figure out basic clone functions
// clone functions findBasicCloneFunctions(recoveredClasses);
findCloneFunctions(recoveredClasses);
// This has to be here. It needs all the info from the previously run methods to do this. // This has to be here. It needs all the info from the previously run methods to do this.
// Finds the constructors that have multiple basic blocks, reference the vftable not in the // Finds the constructors that have multiple basic blocks, reference the vftable not in the
@ -1338,6 +1329,8 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
} }
/** /**
* Method to recover parent information, including class offsets, vbase structure and its offset and address if applicable, and whether * Method to recover parent information, including class offsets, vbase structure and its offset and address if applicable, and whether
* the parent is regularly or virtually inherited * the parent is regularly or virtually inherited
@ -1845,11 +1838,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
getParentOrderMap(recoveredClass, ancestorsAllowedToMap); getParentOrderMap(recoveredClass, ancestorsAllowedToMap);
if (sortedOrder.size() != parentOrderMap.size()) { if (sortedOrder.size() != parentOrderMap.size()) {
// if (DEBUG) { Msg.debug(this,
// println(recoveredClass.getName() + recoveredClass.getName() +
// " has mismatch between vftable and parent order map sizes " + " has mismatch between vftable and parent order map sizes " +
// sortedOrder.size() + " vs " + parentOrderMap.size()); sortedOrder.size() + " vs " + parentOrderMap.size());
// }
return; return;
} }
@ -1955,6 +1947,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
Function referencedFunction = Function referencedFunction =
extendedFlatAPI.getReferencedFunction(classReferenceAddress, true); extendedFlatAPI.getReferencedFunction(classReferenceAddress, true);
if (referencedFunction == null) { if (referencedFunction == null) {
continue; continue;
} }