Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/GP-2075_ghidra007_vector_scalar_…
Browse files Browse the repository at this point in the history
…deleting_destructors--SQUASHED'
  • Loading branch information
ryanmkurtz committed Jun 9, 2022
2 parents 624a12b + 02db970 commit e55bdc3
Showing 1 changed file with 176 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
private static final int NONE = -1;
private static final int UNKNOWN = -2;

private static final String DELETING_DESTRUCTOR = "deleting_destructor";
private static final String SCALAR_DELETING_DESCTRUCTOR = "scalar_deleting_destructor";
private static final String VECTOR_DELETING_DESCTRUCTOR = "vector_deleting_destructor";

boolean isPDBLoaded;

public RTTIWindowsClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
Expand Down Expand Up @@ -177,6 +181,10 @@ public List<RecoveredClass> createRecoveredClasses() throws Exception {
// create better vftable labels for multi vftable classes
updateMultiVftableLabels(recoveredClasses);
removeEmptyClassesAndStructures();

// fix up deleting destructors to have vector and scalar names and to split
// non-contiguous ones into two seaparate functions
fixUpDeletingDestructors(recoveredClasses);
}

return recoveredClasses;
Expand Down Expand Up @@ -2660,4 +2668,172 @@ private void updateMultiVftableLabels(List<RecoveredClass> recoveredClasses)
}
}

/**
* Method to fixup previously found deleting destructors's symbols to determine if they are
* scalar or vector ones and name appropriately. In the non-contiguous case, split into two
* functions and name accordingly.
* @param recoveredClasses the list of classes to processes
* @throws CancelledException if cancelled
*/
private void fixUpDeletingDestructors(List<RecoveredClass> recoveredClasses)
throws CancelledException {

List<Function> processedFunctions = new ArrayList<>();

for (RecoveredClass recoveredClass : recoveredClasses) {
monitor.checkCanceled();

List<Function> deletingDestructors = recoveredClass.getDeletingDestructors();

if (deletingDestructors.isEmpty()) {
continue;
}

for (Function function : deletingDestructors) {
monitor.checkCanceled();

if (processedFunctions.contains(function)) {
continue;
}

AddressSetView body = function.getBody();
int numAddressRanges = body.getNumAddressRanges();

// fixup contigous dd function
if (numAddressRanges == 1) {
fixupContiguousDeletingDestructorSymbols(function);
processedFunctions.add(function);
}
else if (numAddressRanges == 2) {
// else fixup split dd function
Function scalarDeletingDestructor = createSplitDeletingDestructorFunction(body);
if (scalarDeletingDestructor == null) {
Msg.debug(this, "Could not fixup split deleting destructor function: " +
function.getEntryPoint());
continue;
}
fixupSplitDeletingDestructorSymbols(function, scalarDeletingDestructor);
processedFunctions.add(function);
}
// else if > 2 do nothing - not sure how to handle or even if they exist
}
}
}

/**
* Method to fixup the given functoin as a contiguous deleting destructor which means it is
* both a scalar and vector deleting destructor and needs both names. Some functions are deleting
* destructors for multiple classes so all of the symbols need to be updated.
* @param function the given function
* @throws CancelledException if cancelled
*/
private void fixupContiguousDeletingDestructorSymbols(Function function)
throws CancelledException {

Symbol[] functionSymbols = symbolTable.getSymbols(function.getEntryPoint());

Address functionAddress = function.getEntryPoint();

api.createBookmark(functionAddress, "Deleting Destructor Fixup",
"Scalar and Vector Deleting Destructor");

try {
for (Symbol functionSymbol : functionSymbols) {
monitor.checkCanceled();

// skip any symbols at function that are not dds ie fid mangled names
if (!functionSymbol.getName().contains(DELETING_DESTRUCTOR)) {
continue;
}

functionSymbol.setName(SCALAR_DELETING_DESCTRUCTOR, functionSymbol.getSource());

Symbol secondaryLabel = symbolTable.createLabel(functionAddress,
VECTOR_DELETING_DESCTRUCTOR, SourceType.ANALYSIS);
secondaryLabel.setNamespace(functionSymbol.getParentNamespace());

}
}
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
Msg.debug(this,
"Could not fixup one or more deleting destructor symbols for function: " +
functionAddress);
}
}

/**
* Method to create a second function in the case where a deleting destructor is of the type
* vector dd function jumps to scalar dd function and fixup the jump to be a call return flow
* override
* @param body the given function body
* @return the newly created jumped to function or null if it cannot be created
*/
private Function createSplitDeletingDestructorFunction(AddressSetView body) {

if (body.getNumAddressRanges() != 2) {
return null;
}
AddressRange firstRange = body.getFirstRange();
Address maxAddressofFirstRange = firstRange.getMaxAddress();
Instruction instructionContaining =
api.getInstructionContaining(maxAddressofFirstRange);
if (!instructionContaining.getFlowType().isJump()) {
return null;
}
AddressRange lastRange = body.getLastRange();
Address minAddressOfLastRange = lastRange.getMinAddress();
Reference reference =
api.getReference(instructionContaining, minAddressOfLastRange);
if (reference == null) {
return null;
}
instructionContaining.setFlowOverride(FlowOverride.CALL_RETURN);
Function newFunction = api.createFunction(minAddressOfLastRange, null);
return newFunction;
}

/**
* Method to fixup the deleting destructor symbols in a split deleting destructor case given
* the two functions split earlier from the original function. Some functions are deleting
* destructors for multiple classes so all of the symbols need to be updated.
* @param vectorDDFunction the vector deleting destructor function
* @param scalarDDFunction the scalar deleting destructor function
* @throws CancelledException if cancelled
*/
private void fixupSplitDeletingDestructorSymbols(Function vectorDDFunction,
Function scalarDDFunction) throws CancelledException {

Symbol[] functionSymbols = symbolTable.getSymbols(vectorDDFunction.getEntryPoint());

try {
for (Symbol functionSymbol : functionSymbols) {
monitor.checkCanceled();

// skip any symbols at function that are not dds ie fid mangled names
if (!functionSymbol.getName().contains(DELETING_DESTRUCTOR)) {
continue;
}

functionSymbol.setName(VECTOR_DELETING_DESCTRUCTOR, functionSymbol.getSource());

Symbol secondaryLabel = symbolTable.createLabel(scalarDDFunction.getEntryPoint(),
SCALAR_DELETING_DESCTRUCTOR, SourceType.ANALYSIS);
secondaryLabel.setNamespace(functionSymbol.getParentNamespace());

}
}
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
Msg.debug(this,
"Could not fixup one or more deleting destructor symbols for split functions: " +
vectorDDFunction.getEntryPoint() + " and " + scalarDDFunction.getEntryPoint());
}

api.createBookmark(scalarDDFunction.getEntryPoint(), "Deleting Destructor Fixup",
"Scalar Deleting Destructor");
api.createBookmark(vectorDDFunction.getEntryPoint(), "Deleting Destructor Fixup",
"Vector Deleting Destructor");

}

}

0 comments on commit e55bdc3

Please sign in to comment.