GP-2010 updated to use preferred root class folder and removed code that

replaced other class structs
This commit is contained in:
ghidra007 2022-05-13 22:47:22 +00:00
parent d7fc209657
commit 37f87c4874
8 changed files with 28 additions and 248 deletions

View file

@ -47,7 +47,7 @@ public class ApplyClassFunctionDefinitionUpdatesScript extends GhidraScript {
} }
RecoveredClassHelper classHelper = new RecoveredClassHelper(currentProgram, currentLocation, RecoveredClassHelper classHelper = new RecoveredClassHelper(currentProgram, currentLocation,
state.getTool(), this, false, false, false, false, monitor); state.getTool(), this, false, false, false, monitor);
DataTypeManagerService dtms = state.getTool().getService(DataTypeManagerService.class); DataTypeManagerService dtms = state.getTool().getService(DataTypeManagerService.class);
List<DataType> selectedDatatypes = dtms.getSelectedDatatypes(); List<DataType> selectedDatatypes = dtms.getSelectedDatatypes();

View file

@ -47,7 +47,7 @@ public class ApplyClassFunctionSignatureUpdatesScript extends GhidraScript {
} }
RecoveredClassHelper classHelper = new RecoveredClassHelper(currentProgram, currentLocation, RecoveredClassHelper classHelper = new RecoveredClassHelper(currentProgram, currentLocation,
state.getTool(), this, false, false, false, false, monitor); state.getTool(), this, false, false, false, monitor);
if(currentAddress == null) { if(currentAddress == null) {
println("Cursor must be in a class function."); println("Cursor must be in a class function.");

View file

@ -33,7 +33,7 @@ public class FindOperatorDeletesAndNewsScript extends GhidraScript {
} }
RecoveredClassHelper classHelper = new RecoveredClassHelper(currentProgram, currentLocation, RecoveredClassHelper classHelper = new RecoveredClassHelper(currentProgram, currentLocation,
state.getTool(), this, false, false, false, false, monitor); state.getTool(), this, false, false, false, monitor);
List<Address> discoveredOperatorDeletes = List<Address> discoveredOperatorDeletes =
getFunctionAddressList(classHelper.findOperatorDeletes()); getFunctionAddressList(classHelper.findOperatorDeletes());

View file

@ -130,12 +130,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
// show shortened class template names in class structure field names // show shortened class template names in class structure field names
private static final boolean USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS = true; private static final boolean USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS = true;
// replace defined existing class structures (ie pdb, fid, demangler, or other)with ones created by
// this script and rename the existing ones with a _REPLACED suffix
// NOTE: currently does not replace DWARF
// NEW OPTION:
private static final boolean REPLACE_EXISTING_CLASS_STRUCTURES = true;
private static final String CLASS_DATA_STRUCT_NAME = "_data"; private static final String CLASS_DATA_STRUCT_NAME = "_data";
private static final String CONSTRUCTOR_BOOKMARK = "CONSTRUCTOR"; private static final String CONSTRUCTOR_BOOKMARK = "CONSTRUCTOR";
@ -143,30 +137,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
private static final String INDETERMINATE_BOOKMARK = "INDETERMINATE"; private static final String INDETERMINATE_BOOKMARK = "INDETERMINATE";
// DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES
// If replacedClassStructuresOption is set to the following, no replaced structures will be removed
// from the data type manager
// REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES
// If replacedClassStructuresOption is set to the following, only empty existing class structures
// that were replaced by this script will be removed from the data type manager
// REMOVE_ALL_REPLACED_CLASS_STRUCTURES
// If replacedClassStructuresOption is set to the following, all existing class structures that
// were replaced by this script, including non-emtpy ones, will be removed from the data type
// manager
private static enum removeOption {
DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES,
REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES,
REMOVE_ALL_REPLACED_CLASS_STRUCTURES
}
// NEW OPTION -
// This option allows the user to decide whether and how to remove replaced existing class structures
// using one of the above three flags
removeOption replacedClassStructuresOption =
removeOption.DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES;
boolean programHasRTTIApplied = false; boolean programHasRTTIApplied = false;
boolean hasDebugSymbols; boolean hasDebugSymbols;
boolean isGcc = false; boolean isGcc = false;
@ -198,7 +168,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
recoverClassesFromRTTI = recoverClassesFromRTTI =
new RTTIWindowsClassRecoverer(currentProgram, currentLocation, state.getTool(), new RTTIWindowsClassRecoverer(currentProgram, currentLocation, state.getTool(),
this, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, this, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
nameVfunctions, hasDebugSymbols, REPLACE_EXISTING_CLASS_STRUCTURES, monitor); nameVfunctions, hasDebugSymbols, monitor);
} }
else if (isGcc()) { else if (isGcc()) {
@ -221,7 +191,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
recoverClassesFromRTTI = recoverClassesFromRTTI =
new RTTIGccClassRecoverer(currentProgram, currentLocation, state.getTool(), this, new RTTIGccClassRecoverer(currentProgram, currentLocation, state.getTool(), this,
BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
nameVfunctions, hasDebugSymbols, REPLACE_EXISTING_CLASS_STRUCTURES, monitor); nameVfunctions, hasDebugSymbols, monitor);
} }
else { else {
println("This script will not work on this program type"); println("This script will not work on this program type");
@ -265,6 +235,9 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
out = new PrintWriter(outputFile); out = new PrintWriter(outputFile);
} }
currentProgram.setPreferredRootNamespaceCategoryPath(
"/" + RecoveredClassHelper.DTM_CLASS_DATA_FOLDER_NAME);
if (FIXUP_PROGRAM) { if (FIXUP_PROGRAM) {
println( println(
"Checking for missing RTTI information and undefined constructor/destructor functions and creating if possible " + "Checking for missing RTTI information and undefined constructor/destructor functions and creating if possible " +
@ -313,17 +286,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
showGraph(graph); showGraph(graph);
} }
if (replacedClassStructuresOption == removeOption.REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES) {
println("Removing all empty replaced class structures from the data type manager");
recoverClassesFromRTTI.removeReplacedClassStructures(recoveredClasses, false);
}
if (replacedClassStructuresOption == removeOption.REMOVE_ALL_REPLACED_CLASS_STRUCTURES) {
println(
"Removing all replaced class structures from the data type manager, including non-empty ones");
recoverClassesFromRTTI.removeReplacedClassStructures(recoveredClasses, true);
}
decompilerUtils.disposeDecompilerInterface(); decompilerUtils.disposeDecompilerInterface();
} }

View file

@ -43,11 +43,9 @@ public class RTTIClassRecoverer extends RecoveredClassHelper {
RTTIClassRecoverer(Program program, ProgramLocation location, PluginTool tool, RTTIClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates, FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
boolean nameVfunctions, boolean hasDebugSymbols, boolean replaceClassStructures, boolean nameVfunctions, boolean hasDebugSymbols, TaskMonitor monitor) throws Exception {
TaskMonitor monitor) throws Exception {
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions, super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions,
replaceClassStructures,
monitor); monitor);
this.program = program; this.program = program;

View file

@ -76,13 +76,12 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
public RTTIGccClassRecoverer(Program program, ProgramLocation location, PluginTool tool, public RTTIGccClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates, FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
boolean nameVfunctions, boolean isDwarfLoaded, boolean replaceExistingClassStructures, boolean nameVfunctions, boolean isDwarfLoaded,
TaskMonitor monitor) throws Exception { TaskMonitor monitor) throws Exception {
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions, super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions,
replaceExistingClassStructures, isDwarfLoaded, monitor); isDwarfLoaded, monitor);
this.isDwarfLoaded = isDwarfLoaded; this.isDwarfLoaded = isDwarfLoaded;
this.replaceClassStructs = replaceExistingClassStructures;
} }
@Override @Override

View file

@ -69,11 +69,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
public RTTIWindowsClassRecoverer(Program program, ProgramLocation location, PluginTool tool, public RTTIWindowsClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates, FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
boolean nameVFunctions, boolean isPDBLoaded, boolean replaceClassStructures, boolean nameVFunctions, boolean isPDBLoaded, TaskMonitor monitor) throws Exception {
TaskMonitor monitor) throws Exception {
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVFunctions, super(program, location, tool, api, createBookmarks, useShortTemplates, nameVFunctions,
isPDBLoaded, replaceClassStructures, monitor); isPDBLoaded, monitor);
this.isPDBLoaded = isPDBLoaded; this.isPDBLoaded = isPDBLoaded;

View file

@ -144,11 +144,10 @@ public class RecoveredClassHelper {
boolean createBookmarks; boolean createBookmarks;
boolean useShortTemplates; boolean useShortTemplates;
boolean nameVfunctions; boolean nameVfunctions;
boolean replaceClassStructures;
public RecoveredClassHelper(Program program, ProgramLocation location, PluginTool tool, public RecoveredClassHelper(Program program, ProgramLocation location, PluginTool tool,
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates, FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
boolean nameVunctions, boolean replaceClassStructures, TaskMonitor monitor) boolean nameVunctions, TaskMonitor monitor)
throws Exception { throws Exception {
this.monitor = monitor; this.monitor = monitor;
@ -165,7 +164,6 @@ public class RecoveredClassHelper {
this.createBookmarks = createBookmarks; this.createBookmarks = createBookmarks;
this.useShortTemplates = useShortTemplates; this.useShortTemplates = useShortTemplates;
this.nameVfunctions = nameVunctions; this.nameVfunctions = nameVunctions;
this.replaceClassStructures = replaceClassStructures;
globalNamespace = (GlobalNamespace) program.getGlobalNamespace(); globalNamespace = (GlobalNamespace) program.getGlobalNamespace();
@ -3276,13 +3274,6 @@ public class RecoveredClassHelper {
true); true);
} }
// check to see if the "this" data type is an empty placeholder for the class
// structure and replace it with the one that was just created by the script
//NEW
if (replaceClassStructures) {
replaceClassStructure(constructorFunction, className, classStruct);
}
// if current decompiler function return type is a pointer then set the return type // if current decompiler function return type is a pointer then set the return type
// to a pointer to the class structure, otherwise if it is a void, make it a void so the // to a pointer to the class structure, otherwise if it is a void, make it a void so the
// listing has void too, otherwise, leave it as is, probably a void // listing has void too, otherwise, leave it as is, probably a void
@ -3314,6 +3305,20 @@ public class RecoveredClassHelper {
DataType classPointerDataType = dataTypeManager.getPointer(classStruct); DataType classPointerDataType = dataTypeManager.getPointer(classStruct);
constructorFunction.setReturnType(classPointerDataType, SourceType.ANALYSIS); constructorFunction.setReturnType(classPointerDataType, SourceType.ANALYSIS);
} }
// if neither and it is a FID function change it to undefined so the decompiler will
// recompute it
else if (isFidFunction(constructorFunction)) {
DataType undefinedDT = null;
if (defaultPointerSize == 4) {
undefinedDT = new Undefined4DataType();
}
if (defaultPointerSize == 8) {
undefinedDT = new Undefined8DataType();
}
if (undefinedDT != null) {
constructorFunction.setReturnType(undefinedDT, SourceType.ANALYSIS);
}
}
} }
} }
@ -3358,13 +3363,6 @@ public class RecoveredClassHelper {
true); true);
} }
// check to see if the "this" data type is an empty placeholder for the class
// structure and replace it with the one that was just created by the script
//NEW
if (replaceClassStructures) {
replaceClassStructure(destructorFunction, className, classStruct);
}
destructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS); destructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
} }
} }
@ -3412,14 +3410,6 @@ public class RecoveredClassHelper {
true, true); true, true);
} }
// check to see if the "this" data type is an empty placeholder for the class
// structure and replace it with the one that was just created by the script
//NEW
if (replaceClassStructures) {
replaceClassStructure(vbaseDestructorFunction, recoveredClass.getName(),
classStruct);
}
vbaseDestructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS); vbaseDestructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
} }
@ -3527,161 +3517,6 @@ public class RecoveredClassHelper {
} }
} }
/**
* Method to replace the program's current class structure, only if an empty placeholder structure,
* with the one generated by this script
* @param function a class method with current class structure applied
* @param className the given class name
* @param newClassStructure the new structure to replace the old with
* @throws DataTypeDependencyException if there is a data dependency exception when replacing
* @throws CancelledException if cancelled
*/
public void replaceClassStructure(Function function, String className,
Structure newClassStructure) throws DataTypeDependencyException, CancelledException {
Parameter thisParam = function.getParameter(0);
if (thisParam == null) {
return;
}
DataType dataType = thisParam.getDataType();
if (dataType instanceof Pointer) {
Pointer ptr = (Pointer) dataType;
DataType baseDataType = ptr.getDataType();
if (!baseDataType.equals(newClassStructure) &&
baseDataType.getName().equals(className)) {
// check if fid demangler or pdb - don't replace user ones
if (!isReplaceableType(function.getEntryPoint(), baseDataType)) {
return;
}
// create copy of existing one
DataType baseDataTypeCopy = baseDataType.copy(dataTypeManager);
renameDataType(baseDataTypeCopy, baseDataType.getName() + "_REPLACED");
// replace the other with the new one
dataTypeManager.replaceDataType(baseDataType, newClassStructure, false);
// // remove original folder if it is empty after the replace
// in future if decide to just remove the other ones, then do the following
// CategoryPath originalPath = baseDataType.getCategoryPath();
// Category category = dataTypeManager.getCategory(originalPath);
// Category parentCategory = category.getParent();
// if (parentCategory != null) {
// parentCategory.removeEmptyCategory(category.getName(), monitor);
// }
}
}
}
private void renameDataType(DataType dataType, String name) throws CancelledException {
boolean renamed = false;
int oneup = 2;
while (!renamed) {
monitor.checkCanceled();
try {
dataType.setName(name);
dataTypeManager.resolve(dataType, DataTypeConflictHandler.DEFAULT_HANDLER);
renamed = true;
}
catch (InvalidNameException | DuplicateNameException e) {
name = name + oneup++;
renamed = false;
}
}
}
private boolean isReplaceableType(Address address, DataType dataType) {
// return false if it isn't even a structure
if (!(dataType instanceof Structure)) {
return false;
}
String categoryPath = dataType.getPathName();
if (categoryPath.startsWith("/Demangler")) {
return true;
}
if (categoryPath.contains(".pdb")) {
return true;
}
if (categoryPath.contains("DWARF")) {
return true;
}
// test to see if the data type is an empty structure with "PlaceHolder Class Structure" in
// the description
Structure structure = (Structure) dataType;
if (structure.isNotYetDefined() &&
structure.getDescription().equals("PlaceHolder Class Structure")) {
return true;
}
if (program.getBookmarkManager()
.getBookmark(address, BookmarkType.ANALYSIS, "Function ID Analyzer") != null) {
return true;
}
return false;
}
/**
* Method to remove existing class structures from the data type manager that were replaced by
* newly created class structures and that have the "_REPLACED" suffix on them
* @param recoveredClasses list of given recovered classes
* @param removeNonEmpty if true, remove not only the empty replaced class structures but
* also the non-empty ones.
* @throws CancelledException if cancelled
*/
public void removeReplacedClassStructures(List<RecoveredClass> recoveredClasses,
boolean removeNonEmpty) throws CancelledException {
if (recoveredClasses.isEmpty()) {
return;
}
for (RecoveredClass recoveredClass : recoveredClasses) {
monitor.checkCanceled();
// first get the new class structure and verify it exists - don't remove others if
// new one doesn't exist
DataType classStructureDataType = dataTypeManager
.getDataType(recoveredClass.getClassPath(), recoveredClass.getName());
if (classStructureDataType == null) {
continue;
}
// then find all class structures with name "<className>_REPLACED"
List<DataType> replacedClassDataTypes = new ArrayList<DataType>();
dataTypeManager.findDataTypes(recoveredClass.getName() + "_REPLACED",
replacedClassDataTypes);
if (replacedClassDataTypes.isEmpty()) {
continue;
}
for (DataType replacedClassDataType : replacedClassDataTypes) {
monitor.checkCanceled();
if (!(replacedClassDataType instanceof Structure)) {
continue;
}
if (removeNonEmpty) {
dataTypeManager.remove(replacedClassDataType, monitor);
}
else {
Structure replacedStructure = (Structure) replacedClassDataType;
if (replacedStructure.isNotYetDefined()) {
dataTypeManager.remove(replacedClassDataType, monitor);
}
}
}
}
}
/** /**
* Method to create a new symbol at the given function * Method to create a new symbol at the given function
@ -4546,13 +4381,6 @@ public class RecoveredClassHelper {
continue; continue;
} }
// check to see if the "this" data type is an empty placeholder for the class
// structure and replace it with the one that was just created by the script
//NEW
if (replaceClassStructures) {
replaceClassStructure(vfunction, recoveredClass.getName(), classStruct);
}
String forClassSuffix = getForClassSuffix(vftableStructureName); String forClassSuffix = getForClassSuffix(vftableStructureName);
String functionDefName = vfunction.getName(); String functionDefName = vfunction.getName();
int indexOfSuffix = functionDefName.indexOf(forClassSuffix); int indexOfSuffix = functionDefName.indexOf(forClassSuffix);
@ -5091,12 +4919,6 @@ public class RecoveredClassHelper {
className + "_Constructor_or_Destructor", classNamespace, false, false); className + "_Constructor_or_Destructor", classNamespace, false, false);
} }
// check to see if the "this" data type is an empty placeholder for the class
// structure and replace it with the one that was just created by the script
//NEW
if (replaceClassStructures) {
replaceClassStructure(indeterminateFunction, className, classStruct);
}
} }
} }