mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 13:24:41 +08:00
Merge remote-tracking branch 'origin/Ghidra_10.1'
This commit is contained in:
@@ -29,7 +29,7 @@ public interface PtySession {
|
|||||||
* @return the status code, if applicable and implemented
|
* @return the status code, if applicable and implemented
|
||||||
* @throws InterruptedException if the wait is interrupted
|
* @throws InterruptedException if the wait is interrupted
|
||||||
*/
|
*/
|
||||||
Integer waitExited() throws InterruptedException;
|
int waitExited() throws InterruptedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take the greatest efforts to terminate the session (leader and descendants)
|
* Take the greatest efforts to terminate the session (leader and descendants)
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ public class LocalProcessPtySession implements PtySession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer waitExited() throws InterruptedException {
|
public int waitExited() throws InterruptedException {
|
||||||
return process.waitFor();
|
return process.waitFor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class SshPtySession implements PtySession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer waitExited() throws InterruptedException {
|
public int waitExited() throws InterruptedException {
|
||||||
// Doesn't look like there's a clever way to wait. So do the spin sleep :(
|
// Doesn't look like there's a clever way to wait. So do the spin sleep :(
|
||||||
while (!channel.isEOF()) {
|
while (!channel.isEOF()) {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class LinuxPtyTest {
|
|||||||
PtySession bash =
|
PtySession bash =
|
||||||
pty.getChild().session(new String[] { DummyProc.which("bash") }, null);
|
pty.getChild().session(new String[] { DummyProc.which("bash") }, null);
|
||||||
pty.getParent().getOutputStream().write("exit\n".getBytes());
|
pty.getParent().getOutputStream().write("exit\n".getBytes());
|
||||||
assertEquals(0, bash.waitExited().intValue());
|
assertEquals(0, bash.waitExited());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ public class LinuxPtyTest {
|
|||||||
* NOTE: Java subprocess dies with code 1 on unhandled exception. TODO: Is there a nice
|
* NOTE: Java subprocess dies with code 1 on unhandled exception. TODO: Is there a nice
|
||||||
* way to distinguish whether the code is from java or the execed image?
|
* way to distinguish whether the code is from java or the execed image?
|
||||||
*/
|
*/
|
||||||
assertEquals(1, dies.waitExited().intValue());
|
assertEquals(1, dies.waitExited());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ public class LinuxPtyTest {
|
|||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
assertEquals("Early exit with wrong code", expected,
|
assertEquals("Early exit with wrong code", expected,
|
||||||
session.waitExited().intValue());
|
session.waitExited());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {
|
catch (InterruptedException e) {
|
||||||
@@ -159,7 +159,7 @@ public class LinuxPtyTest {
|
|||||||
assertTrue("Not 'exit 3' or 'BASH:exit 3': '" + line + "'",
|
assertTrue("Not 'exit 3' or 'BASH:exit 3': '" + line + "'",
|
||||||
Set.of("BASH:exit 3", "exit 3").contains(line));
|
Set.of("BASH:exit 3", "exit 3").contains(line));
|
||||||
|
|
||||||
assertEquals(3, bash.waitExited().intValue());
|
assertEquals(3, bash.waitExited());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +214,7 @@ public class LinuxPtyTest {
|
|||||||
writer.flush();
|
writer.flush();
|
||||||
assertTrue(Set.of("BASH:exit 3", "exit 3").contains(reader.readLine()));
|
assertTrue(Set.of("BASH:exit 3", "exit 3").contains(reader.readLine()));
|
||||||
|
|
||||||
assertEquals(3, bash.waitExited().intValue());
|
assertEquals(3, bash.waitExited());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class SshPtyTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
out.write("exit\n".getBytes("UTF-8"));
|
out.write("exit\n".getBytes("UTF-8"));
|
||||||
out.flush();
|
out.flush();
|
||||||
new StreamPumper(pty.getParent().getInputStream(), System.out).start();
|
new StreamPumper(pty.getParent().getInputStream(), System.out).start();
|
||||||
assertEquals(0, bash.waitExited().intValue());
|
assertEquals(0, bash.waitExited());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ public class ApplyClassFunctionDefinitionUpdatesScript extends GhidraScript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecoveredClassUtils classUtils = new RecoveredClassUtils(currentProgram, currentLocation,
|
RecoveredClassUtils classUtils = new RecoveredClassUtils(currentProgram, currentLocation,
|
||||||
state.getTool(), this, false, false, false, monitor);
|
state.getTool(), this, false, false, false, false, monitor);
|
||||||
|
|
||||||
Namespace classNamespace = classUtils.getClassNamespace(currentAddress);
|
Namespace classNamespace = classUtils.getClassNamespace(currentAddress);
|
||||||
if (classNamespace == null) {
|
if (classNamespace == null) {
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ public class ApplyClassFunctionSignatureUpdatesScript extends GhidraScript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecoveredClassUtils classUtils = new RecoveredClassUtils(currentProgram, currentLocation,
|
RecoveredClassUtils classUtils = new RecoveredClassUtils(currentProgram, currentLocation,
|
||||||
state.getTool(), this, false, false, false, monitor);
|
state.getTool(), this, false, false, false, false, monitor);
|
||||||
|
|
||||||
Namespace classNamespace = classUtils.getClassNamespace(currentAddress);
|
Namespace classNamespace = classUtils.getClassNamespace(currentAddress);
|
||||||
if (classNamespace == null) {
|
if (classNamespace == null) {
|
||||||
|
|||||||
@@ -121,6 +121,12 @@ 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";
|
||||||
@@ -128,6 +134,24 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||||||
|
|
||||||
private static final String INDETERMINATE_BOOKMARK = "INDETERMINATE";
|
private static final String INDETERMINATE_BOOKMARK = "INDETERMINATE";
|
||||||
|
|
||||||
|
// If replacedClassStructuresOption is set to the following, no replaced structures will be removed
|
||||||
|
// from the data type manager
|
||||||
|
private static final int DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES = 0;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
private static final int REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES = 1;
|
||||||
|
|
||||||
|
// 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 final int REMOVE_ALL_REPLACED_CLASS_STRUCTURES = 2;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
int replacedClassStructuresOption = DO_NOT_REMOVE_REPLACED_CLASS_STRUCTURES;
|
||||||
|
|
||||||
boolean programHasRTTIApplied = false;
|
boolean programHasRTTIApplied = false;
|
||||||
boolean hasDebugSymbols;
|
boolean hasDebugSymbols;
|
||||||
boolean isGcc = false;
|
boolean isGcc = false;
|
||||||
@@ -162,6 +186,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||||||
recoverClassesFromRTTI = new RTTIWindowsClassRecoverer(currentProgram,
|
recoverClassesFromRTTI = new RTTIWindowsClassRecoverer(currentProgram,
|
||||||
currentLocation, state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
|
currentLocation, state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
|
||||||
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, hasDebugSymbols,
|
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, hasDebugSymbols,
|
||||||
|
REPLACE_EXISTING_CLASS_STRUCTURES,
|
||||||
monitor);
|
monitor);
|
||||||
}
|
}
|
||||||
else if (isGcc()) {
|
else if (isGcc()) {
|
||||||
@@ -182,6 +207,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||||||
recoverClassesFromRTTI = new RTTIGccClassRecoverer(currentProgram, currentLocation,
|
recoverClassesFromRTTI = new RTTIGccClassRecoverer(currentProgram, currentLocation,
|
||||||
state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
|
state.getTool(), this, BOOKMARK_FOUND_FUNCTIONS,
|
||||||
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, hasDebugSymbols,
|
USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS, nameVfunctions, hasDebugSymbols,
|
||||||
|
REPLACE_EXISTING_CLASS_STRUCTURES,
|
||||||
monitor);
|
monitor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -275,6 +301,17 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
|||||||
showGraph(graph);
|
showGraph(graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (replacedClassStructuresOption == REMOVE_EMPTY_REPLACED_CLASS_STRUCTURES) {
|
||||||
|
println("Removing all empty replaced class structures from the data type manager");
|
||||||
|
recoverClassesFromRTTI.removeReplacedClassStructures(recoveredClasses, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replacedClassStructuresOption == 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,14 @@ public class RTTIClassRecoverer extends RecoveredClassUtils {
|
|||||||
TaskMonitor monitor;
|
TaskMonitor monitor;
|
||||||
boolean hasDebugSymbols;
|
boolean hasDebugSymbols;
|
||||||
|
|
||||||
|
|
||||||
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 nameVfunctions, boolean hasDebugSymbols, boolean replaceClassStructures,
|
||||||
TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -69,15 +69,19 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||||||
new HashMap<RecoveredClass, Map<RecoveredClass, Long>>();
|
new HashMap<RecoveredClass, Map<RecoveredClass, Long>>();
|
||||||
|
|
||||||
boolean isDwarfLoaded;
|
boolean isDwarfLoaded;
|
||||||
|
boolean replaceClassStructs;
|
||||||
|
|
||||||
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, TaskMonitor monitor) {
|
boolean nameVfunctions, boolean isDwarfLoaded, boolean replaceExistingClassStructures,
|
||||||
|
TaskMonitor monitor) {
|
||||||
|
|
||||||
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions,
|
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVfunctions,
|
||||||
|
replaceExistingClassStructures,
|
||||||
isDwarfLoaded,
|
isDwarfLoaded,
|
||||||
monitor);
|
monitor);
|
||||||
this.isDwarfLoaded = isDwarfLoaded;
|
this.isDwarfLoaded = isDwarfLoaded;
|
||||||
|
this.replaceClassStructs = replaceExistingClassStructures;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2898,12 +2902,14 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||||||
Structure classStruct = createSimpleClassStructure(recoveredClass, vfPointerDataTypes);
|
Structure classStruct = createSimpleClassStructure(recoveredClass, vfPointerDataTypes);
|
||||||
|
|
||||||
// check for DWARF -- if none add c/d/etc to class
|
// check for DWARF -- if none add c/d/etc to class
|
||||||
|
//TODO: if decide to replace dwarf data types then remove this check so the replaces
|
||||||
|
// in the following methods can replace the dwarf data types
|
||||||
if (!isDwarfLoaded) {
|
if (!isDwarfLoaded) {
|
||||||
|
|
||||||
// Now that we have a class data type
|
// Now that we have a class data type
|
||||||
// name constructor and destructor functions and put into the class namespace
|
// name constructor and destructor functions and put into the class namespace
|
||||||
addConstructorsToClassNamespace(recoveredClass, classStruct);
|
addConstructorsToClassNamespace(recoveredClass, classStruct);
|
||||||
addDestructorsToClassNamespace(recoveredClass);
|
addDestructorsToClassNamespace(recoveredClass, classStruct);
|
||||||
// addNonThisDestructorsToClassNamespace(recoveredClass);
|
// addNonThisDestructorsToClassNamespace(recoveredClass);
|
||||||
// addVbaseDestructorsToClassNamespace(recoveredClass);
|
// addVbaseDestructorsToClassNamespace(recoveredClass);
|
||||||
// addVbtableToClassNamespace(recoveredClass);
|
// addVbtableToClassNamespace(recoveredClass);
|
||||||
@@ -2914,7 +2920,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||||||
// createIndeterminateInlineComments(recoveredClass);
|
// createIndeterminateInlineComments(recoveredClass);
|
||||||
|
|
||||||
// add label on constructor destructor functions that could not be determined which were which
|
// add label on constructor destructor functions that could not be determined which were which
|
||||||
createIndeterminateLabels(recoveredClass);
|
createIndeterminateLabels(recoveredClass, classStruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is done after the class structure is created and added to the dtmanager
|
// This is done after the class structure is created and added to the dtmanager
|
||||||
@@ -2922,7 +2928,8 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
|||||||
// then empty classes will get auto-created in the wrong place
|
// then empty classes will get auto-created in the wrong place
|
||||||
// when the vfunctions are put in the class
|
// when the vfunctions are put in the class
|
||||||
|
|
||||||
fillInAndApplyVftableStructAndNameVfunctions(recoveredClass, vfPointerDataTypes);
|
fillInAndApplyVftableStructAndNameVfunctions(recoveredClass, vfPointerDataTypes,
|
||||||
|
classStruct);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-14
@@ -69,11 +69,11 @@ 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 nameVFunctions, boolean isPDBLoaded, boolean replaceClassStructures,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
|
|
||||||
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVFunctions,
|
super(program, location, tool, api, createBookmarks, useShortTemplates, nameVFunctions,
|
||||||
isPDBLoaded, monitor);
|
isPDBLoaded, replaceClassStructures, monitor);
|
||||||
|
|
||||||
this.isPDBLoaded = isPDBLoaded;
|
this.isPDBLoaded = isPDBLoaded;
|
||||||
|
|
||||||
@@ -2245,32 +2245,35 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
|||||||
|
|
||||||
applyVbtableStructure(recoveredClass);
|
applyVbtableStructure(recoveredClass);
|
||||||
|
|
||||||
// pdb already has good names so only name if no pdb
|
|
||||||
if (!isPDBLoaded) {
|
|
||||||
|
|
||||||
// Now that we have a class data type
|
// Now that we have a class data type
|
||||||
// name constructor and destructor functions and put into the class namespace
|
// name constructor and destructor functions and put into the class namespace
|
||||||
addConstructorsToClassNamespace(recoveredClass, classStruct);
|
// checks are internal for hasDebugSymbols since there
|
||||||
addDestructorsToClassNamespace(recoveredClass);
|
// are also replace methods that need to be called either way
|
||||||
|
addConstructorsToClassNamespace(recoveredClass, classStruct);
|
||||||
|
addDestructorsToClassNamespace(recoveredClass, classStruct);
|
||||||
|
addVbaseDestructorsToClassNamespace(recoveredClass, classStruct);
|
||||||
|
|
||||||
|
if (!hasDebugSymbols) {
|
||||||
addNonThisDestructorsToClassNamespace(recoveredClass);
|
addNonThisDestructorsToClassNamespace(recoveredClass);
|
||||||
addVbaseDestructorsToClassNamespace(recoveredClass);
|
|
||||||
addVbtableToClassNamespace(recoveredClass);
|
addVbtableToClassNamespace(recoveredClass);
|
||||||
|
|
||||||
// add secondary label on functions with inlined constructors or destructors
|
// add secondary label on functions with inlined constructors or destructors
|
||||||
createInlinedConstructorComments(recoveredClass);
|
createInlinedConstructorComments(recoveredClass);
|
||||||
createInlinedDestructorComments(recoveredClass);
|
createInlinedDestructorComments(recoveredClass);
|
||||||
createIndeterminateInlineComments(recoveredClass);
|
createIndeterminateInlineComments(recoveredClass);
|
||||||
|
|
||||||
// add label on constructor destructor functions that could not be determined which were which
|
|
||||||
createIndeterminateLabels(recoveredClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add label on constructor destructor functions that could not be determined which were which
|
||||||
|
createIndeterminateLabels(recoveredClass, classStruct);
|
||||||
|
|
||||||
// This is done after the class structure is created and added to the dtmanager
|
// This is done after the class structure is created and added to the dtmanager
|
||||||
// because if done before the class structures are created
|
// because if done before the class structures are created
|
||||||
// then empty classes will get auto-created in the wrong place
|
// then empty classes will get auto-created in the wrong place
|
||||||
// when the vfunctions are put in the class
|
// when the vfunctions are put in the class
|
||||||
|
fillInAndApplyVftableStructAndNameVfunctions(recoveredClass, vfPointerDataTypes,
|
||||||
fillInAndApplyVftableStructAndNameVfunctions(recoveredClass, vfPointerDataTypes);
|
classStruct);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -144,10 +144,11 @@ public class RecoveredClassUtils {
|
|||||||
boolean createBookmarks;
|
boolean createBookmarks;
|
||||||
boolean useShortTemplates;
|
boolean useShortTemplates;
|
||||||
boolean nameVfunctions;
|
boolean nameVfunctions;
|
||||||
|
boolean replaceClassStructures;
|
||||||
|
|
||||||
public RecoveredClassUtils(Program program, ProgramLocation location, PluginTool tool,
|
public RecoveredClassUtils(Program program, ProgramLocation location, PluginTool tool,
|
||||||
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
|
FlatProgramAPI api, boolean createBookmarks, boolean useShortTemplates,
|
||||||
boolean nameVfunctions, TaskMonitor monitor) {
|
boolean nameVunctions, boolean replaceClassStructures, TaskMonitor monitor) {
|
||||||
|
|
||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
this.program = program;
|
this.program = program;
|
||||||
@@ -162,7 +163,8 @@ public class RecoveredClassUtils {
|
|||||||
|
|
||||||
this.createBookmarks = createBookmarks;
|
this.createBookmarks = createBookmarks;
|
||||||
this.useShortTemplates = useShortTemplates;
|
this.useShortTemplates = useShortTemplates;
|
||||||
this.nameVfunctions = nameVfunctions;
|
this.nameVfunctions = nameVunctions;
|
||||||
|
this.replaceClassStructures = replaceClassStructures;
|
||||||
|
|
||||||
globalNamespace = (GlobalNamespace) program.getGlobalNamespace();
|
globalNamespace = (GlobalNamespace) program.getGlobalNamespace();
|
||||||
|
|
||||||
@@ -3294,12 +3296,17 @@ public class RecoveredClassUtils {
|
|||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
Function constructorFunction = constructorsIterator.next();
|
Function constructorFunction = constructorsIterator.next();
|
||||||
|
|
||||||
createNewSymbolAtFunction(constructorFunction, className, classNamespace, true, true);
|
if (nameVfunctions) {
|
||||||
|
createNewSymbolAtFunction(constructorFunction, className, classNamespace, true,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
// check to see if the "this" data type is an empty placeholder for the class
|
// 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
|
// structure and replace it with the one that was just created by the script
|
||||||
//deleteEmptyClassStructure(constructorFunction, className);
|
//NEW
|
||||||
replaceEmptyClassStructure(constructorFunction, className, classStruct);
|
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
|
||||||
@@ -3337,9 +3344,11 @@ public class RecoveredClassUtils {
|
|||||||
/**
|
/**
|
||||||
* Method to name class destructors and add them to class namespace
|
* Method to name class destructors and add them to class namespace
|
||||||
* @param recoveredClass current class
|
* @param recoveredClass current class
|
||||||
|
* @param classStruct the class structure for the given class
|
||||||
* @throws Exception when cancelled
|
* @throws Exception when cancelled
|
||||||
*/
|
*/
|
||||||
public void addDestructorsToClassNamespace(RecoveredClass recoveredClass) throws Exception {
|
public void addDestructorsToClassNamespace(RecoveredClass recoveredClass, Structure classStruct)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
Namespace classNamespace = recoveredClass.getClassNamespace();
|
Namespace classNamespace = recoveredClass.getClassNamespace();
|
||||||
String className = recoveredClass.getName();
|
String className = recoveredClass.getName();
|
||||||
@@ -3351,8 +3360,17 @@ public class RecoveredClassUtils {
|
|||||||
Function destructorFunction = destructorIterator.next();
|
Function destructorFunction = destructorIterator.next();
|
||||||
String destructorName = "~" + className;
|
String destructorName = "~" + className;
|
||||||
|
|
||||||
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, true,
|
if (nameVfunctions) {
|
||||||
true);
|
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, 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(DataType.VOID, SourceType.ANALYSIS);
|
destructorFunction.setReturnType(DataType.VOID, SourceType.ANALYSIS);
|
||||||
}
|
}
|
||||||
@@ -3384,9 +3402,11 @@ public class RecoveredClassUtils {
|
|||||||
/**
|
/**
|
||||||
* Method to name class vbase destructors and add them to class namespace
|
* Method to name class vbase destructors and add them to class namespace
|
||||||
* @param recoveredClass current class
|
* @param recoveredClass current class
|
||||||
|
* @param classStruct the class structure for the given class
|
||||||
* @throws Exception when cancelled
|
* @throws Exception when cancelled
|
||||||
*/
|
*/
|
||||||
public void addVbaseDestructorsToClassNamespace(RecoveredClass recoveredClass)
|
public void addVbaseDestructorsToClassNamespace(RecoveredClass recoveredClass,
|
||||||
|
Structure classStruct)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Namespace classNamespace = recoveredClass.getClassNamespace();
|
Namespace classNamespace = recoveredClass.getClassNamespace();
|
||||||
@@ -3395,8 +3415,18 @@ public class RecoveredClassUtils {
|
|||||||
if (vbaseDestructorFunction != null) {
|
if (vbaseDestructorFunction != null) {
|
||||||
String destructorName = VBASE_DESTRUCTOR_LABEL;
|
String destructorName = VBASE_DESTRUCTOR_LABEL;
|
||||||
|
|
||||||
createNewSymbolAtFunction(vbaseDestructorFunction, destructorName, classNamespace, true,
|
if (nameVfunctions) {
|
||||||
true);
|
createNewSymbolAtFunction(vbaseDestructorFunction, destructorName, classNamespace,
|
||||||
|
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(DataType.VOID, SourceType.ANALYSIS);
|
vbaseDestructorFunction.setReturnType(DataType.VOID, SourceType.ANALYSIS);
|
||||||
}
|
}
|
||||||
@@ -3505,6 +3535,161 @@ public class RecoveredClassUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: decide whether to replace dwarf or not
|
||||||
|
|
||||||
|
// 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
|
||||||
* @param function the given function
|
* @param function the given function
|
||||||
@@ -4435,11 +4620,12 @@ public class RecoveredClassUtils {
|
|||||||
* Method to fill in the vftable structure with pointers to virtual function signature data types
|
* Method to fill in the vftable structure with pointers to virtual function signature data types
|
||||||
* @param recoveredClass the current class to be processed
|
* @param recoveredClass the current class to be processed
|
||||||
* @param vftableToStructureMap the map from the class's vftables to the correct vftable structure data type
|
* @param vftableToStructureMap the map from the class's vftables to the correct vftable structure data type
|
||||||
|
* @param classStruct the class structure for the given class
|
||||||
* @throws CancelledException when cancelled
|
* @throws CancelledException when cancelled
|
||||||
* @throws Exception if other exception
|
* @throws Exception if other exception
|
||||||
*/
|
*/
|
||||||
public void fillInAndApplyVftableStructAndNameVfunctions(RecoveredClass recoveredClass,
|
public void fillInAndApplyVftableStructAndNameVfunctions(RecoveredClass recoveredClass,
|
||||||
Map<Address, DataType> vftableToStructureMap) throws CancelledException, Exception {
|
Map<Address, DataType> vftableToStructureMap, Structure classStruct) throws CancelledException, Exception {
|
||||||
|
|
||||||
//create function definition for each virtual function and put in vftable structure and
|
//create function definition for each virtual function and put in vftable structure and
|
||||||
// data subfolder
|
// data subfolder
|
||||||
@@ -4468,6 +4654,7 @@ public class RecoveredClassUtils {
|
|||||||
nameVfunctions(recoveredClass, vftableAddress, vftableStructureName);
|
nameVfunctions(recoveredClass, vftableAddress, vftableStructureName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Function> vFunctions = recoveredClass.getVirtualFunctions(vftableAddress);
|
List<Function> vFunctions = recoveredClass.getVirtualFunctions(vftableAddress);
|
||||||
int vfunctionNumber = 1;
|
int vfunctionNumber = 1;
|
||||||
Iterator<Function> vfIterator = vFunctions.iterator();
|
Iterator<Function> vfIterator = vFunctions.iterator();
|
||||||
@@ -4483,6 +4670,13 @@ public class RecoveredClassUtils {
|
|||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
// get the classPath of highest level parent with vfAddress in their vftable
|
// get the classPath of highest level parent with vfAddress in their vftable
|
||||||
classPath =
|
classPath =
|
||||||
getCategoryPathForFunctionSignature(vfunction, recoveredClass, vftableAddress);
|
getCategoryPathForFunctionSignature(vfunction, recoveredClass, vftableAddress);
|
||||||
@@ -5008,9 +5202,11 @@ public class RecoveredClassUtils {
|
|||||||
/**
|
/**
|
||||||
* Method to add label on constructor or destructors but couldn't tell which
|
* Method to add label on constructor or destructors but couldn't tell which
|
||||||
* @param recoveredClass current class
|
* @param recoveredClass current class
|
||||||
|
* @param classStruct the class structure for the given class
|
||||||
* @throws Exception when cancelled
|
* @throws Exception when cancelled
|
||||||
*/
|
*/
|
||||||
public void createIndeterminateLabels(RecoveredClass recoveredClass) throws Exception {
|
public void createIndeterminateLabels(RecoveredClass recoveredClass, Structure classStruct)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
Namespace classNamespace = recoveredClass.getClassNamespace();
|
Namespace classNamespace = recoveredClass.getClassNamespace();
|
||||||
String className = recoveredClass.getName();
|
String className = recoveredClass.getName();
|
||||||
@@ -5020,8 +5216,18 @@ public class RecoveredClassUtils {
|
|||||||
while (unknownsIterator.hasNext()) {
|
while (unknownsIterator.hasNext()) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
Function indeterminateFunction = unknownsIterator.next();
|
Function indeterminateFunction = unknownsIterator.next();
|
||||||
createNewSymbolAtFunction(indeterminateFunction,
|
|
||||||
className + "_Constructor_or_Destructor", classNamespace, false, false);
|
if (nameVfunctions) {
|
||||||
|
createNewSymbolAtFunction(indeterminateFunction,
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user