mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4872 update to all add function to namespaces methods to commit the function so as to not overwrite decomipler when making other changes via listing. Also added check for existing equivalent listing constructor return type before setting it to class structure pointer.
This commit is contained in:
parent
d87add933e
commit
7825f8fd4d
2 changed files with 79 additions and 57 deletions
|
@ -16,10 +16,8 @@
|
|||
//DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS.
|
||||
package classrecovery;
|
||||
|
||||
import docking.options.OptionsService;
|
||||
import ghidra.app.decompiler.*;
|
||||
import ghidra.app.decompiler.component.DecompilerUtils;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
@ -27,7 +25,10 @@ import ghidra.program.model.data.ParameterDefinition;
|
|||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.program.model.pcode.HighFunctionDBUtil.ReturnCommitOption;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DecompilerScriptUtils {
|
||||
|
@ -109,6 +110,30 @@ public class DecompilerScriptUtils {
|
|||
return decompRes.getHighFunction().getFunctionPrototype().getReturnType();
|
||||
}
|
||||
|
||||
public void commitFunction(Function function) {
|
||||
DecompileResults decompRes = decompInterface.decompileFunction(function,
|
||||
decompInterface.getOptions().getDefaultTimeout(), monitor);
|
||||
|
||||
if (decompRes == null || decompRes.getHighFunction() == null ||
|
||||
decompRes.getHighFunction().getFunctionPrototype() == null) {
|
||||
Msg.debug(this, "Couldn't commit params - null high function");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
HighFunctionDBUtil.commitParamsToDatabase(decompRes.getHighFunction(), true,
|
||||
ReturnCommitOption.COMMIT, SourceType.ANALYSIS);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.debug(this, "Couldn't commit params " + e);
|
||||
return;
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
Msg.debug(this, "Couldn't commit params " + e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve the function signature string from the decompiler function prototype. NOTE:
|
||||
* if there is a this param, it will not be included.
|
||||
|
|
|
@ -479,7 +479,8 @@ public class RecoveredClassHelper {
|
|||
return functionToLoadPcodeOps.get(function);
|
||||
}
|
||||
|
||||
public Set<Function> getAllVfunctions(List<Address> vftableAddresses) throws CancelledException {
|
||||
public Set<Function> getAllVfunctions(List<Address> vftableAddresses)
|
||||
throws CancelledException {
|
||||
if (vftableAddresses.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
@ -3294,6 +3295,14 @@ public class RecoveredClassHelper {
|
|||
public void addConstructorsToClassNamespace(RecoveredClass recoveredClass,
|
||||
Structure classStruct) throws Exception {
|
||||
|
||||
DataType undefinedDT = null;
|
||||
if (defaultPointerSize == 4) {
|
||||
undefinedDT = new Undefined4DataType();
|
||||
}
|
||||
if (defaultPointerSize == 8) {
|
||||
undefinedDT = new Undefined8DataType();
|
||||
}
|
||||
|
||||
Namespace classNamespace = recoveredClass.getClassNamespace();
|
||||
String className = recoveredClass.getName();
|
||||
|
||||
|
@ -3310,68 +3319,51 @@ public class RecoveredClassHelper {
|
|||
true);
|
||||
}
|
||||
|
||||
// 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
|
||||
// listing has void too, otherwise, leave it as is, probably a void
|
||||
String returnType = getReturnTypeFromDecompiler(constructorFunction);
|
||||
// commit what the decompiler knows first so that retyping will not
|
||||
// completely overwrite decompiler with listing signature
|
||||
decompilerUtils.commitFunction(constructorFunction);
|
||||
|
||||
// Set error bookmark, add error message, and get the listing return type if the
|
||||
// decompiler return type is null
|
||||
if (returnType == null) {
|
||||
HighFunction highFunction = decompilerUtils.getHighFunction(constructorFunction);
|
||||
if (highFunction == null) {
|
||||
String msg =
|
||||
"Decompiler Error: Failed to decompile function possibly due to the addition of class structure. ";
|
||||
|
||||
String msg1 = "Decompiler Error: Failed to decompile function";
|
||||
String msg2 = ", possibly due to the addition of class structure.";
|
||||
|
||||
Msg.debug(this, msg1 + " at " + constructorFunction.getEntryPoint() + msg2);
|
||||
Msg.debug(this, msg + constructorFunction.getEntryPoint());
|
||||
|
||||
program.getBookmarkManager()
|
||||
.setBookmark(constructorFunction.getEntryPoint(), BookmarkType.ERROR,
|
||||
"Decompiler Error", msg1 + msg2);
|
||||
|
||||
// get the return type from the listing and in some cases it will
|
||||
// indicate the correct type to help determine the below type to add
|
||||
returnType = constructorFunction.getReturnType().getDisplayName();
|
||||
"Decompiler Error", msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (returnType.equals("void")) {
|
||||
constructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||
DataType returnType = highFunction.getFunctionPrototype().getReturnType();
|
||||
if (returnType == null) {
|
||||
Msg.debug(this,
|
||||
"ERROR: Return type is null " + constructorFunction.getEntryPoint());
|
||||
continue;
|
||||
}
|
||||
else if (returnType.contains("*")) {
|
||||
DataType classPointerDataType = dataTypeManager.getPointer(classStruct);
|
||||
constructorFunction.setReturnType(classPointerDataType, SourceType.ANALYSIS);
|
||||
}
|
||||
// if neither and it is a FID function change it to undefined so the decompiler will
|
||||
|
||||
// if a FID function and isn't void or * 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();
|
||||
}
|
||||
String returnTypeString = returnType.getDisplayName();
|
||||
if (isFidFunction(constructorFunction) && returnTypeString != "void" &&
|
||||
!returnTypeString.contains("*")) {
|
||||
|
||||
if (undefinedDT != null) {
|
||||
constructorFunction.setReturnType(undefinedDT, SourceType.ANALYSIS);
|
||||
}
|
||||
}
|
||||
|
||||
// if return type is a pointer then make sure it is the class structure
|
||||
if (returnType.getDisplayName().contains("*")) {
|
||||
DataType classPointerDataType = dataTypeManager.getPointer(classStruct);
|
||||
if (!returnType.isEquivalent(classPointerDataType)) {
|
||||
constructorFunction.setReturnType(classPointerDataType,
|
||||
SourceType.ANALYSIS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the return value from the decompiler signature for the given function
|
||||
* @param function the given function
|
||||
* @return the decompiler return value for the given function
|
||||
*/
|
||||
private String getReturnTypeFromDecompiler(Function function) {
|
||||
|
||||
DataType decompilerReturnType = decompilerUtils.getDecompilerReturnType(function);
|
||||
|
||||
if (decompilerReturnType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return decompilerReturnType.getDisplayName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3399,8 +3391,7 @@ public class RecoveredClassHelper {
|
|||
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, true,
|
||||
true);
|
||||
}
|
||||
|
||||
destructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||
decompilerUtils.commitFunction(destructorFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3426,6 +3417,7 @@ public class RecoveredClassHelper {
|
|||
|
||||
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, false,
|
||||
false);
|
||||
decompilerUtils.commitFunction(destructorFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3450,8 +3442,7 @@ public class RecoveredClassHelper {
|
|||
createNewSymbolAtFunction(vbaseDestructorFunction, destructorName, classNamespace,
|
||||
true, true);
|
||||
}
|
||||
|
||||
vbaseDestructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||
decompilerUtils.commitFunction(vbaseDestructorFunction);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3606,6 +3597,7 @@ public class RecoveredClassHelper {
|
|||
function.getEntryPoint().toString());
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
symbol = lcmd.getSymbol();
|
||||
|
@ -4674,6 +4666,7 @@ public class RecoveredClassHelper {
|
|||
createNewSymbolAtFunction(vfunction, vfunctionName, classNamespace, setPrimary,
|
||||
removeBadFID);
|
||||
}
|
||||
decompilerUtils.commitFunction(vfunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5040,6 +5033,10 @@ public class RecoveredClassHelper {
|
|||
if (nameVfunctions) {
|
||||
createNewSymbolAtFunction(indeterminateFunction,
|
||||
className + "_Constructor_or_Destructor", classNamespace, false, false);
|
||||
// in this case since indeterminate, only commit if script names it
|
||||
// if name flag is not set then it will have correct name from debug and be handled
|
||||
// in other methods (ie addConst, addDest)
|
||||
decompilerUtils.commitFunction(indeterminateFunction);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue