mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-4872_ghidra007_rtti_add_check_for_existing_constructor_return_type--SQUASHED'
This commit is contained in:
commit
be6c7034c9
2 changed files with 79 additions and 57 deletions
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -16,10 +16,8 @@
|
||||||
//DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS.
|
//DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS.
|
||||||
package classrecovery;
|
package classrecovery;
|
||||||
|
|
||||||
import docking.options.OptionsService;
|
|
||||||
import ghidra.app.decompiler.*;
|
import ghidra.app.decompiler.*;
|
||||||
import ghidra.app.decompiler.component.DecompilerUtils;
|
import ghidra.app.decompiler.component.DecompilerUtils;
|
||||||
import ghidra.framework.options.ToolOptions;
|
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
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.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.pcode.*;
|
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;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class DecompilerScriptUtils {
|
public class DecompilerScriptUtils {
|
||||||
|
@ -109,6 +110,30 @@ public class DecompilerScriptUtils {
|
||||||
return decompRes.getHighFunction().getFunctionPrototype().getReturnType();
|
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:
|
* Method to retrieve the function signature string from the decompiler function prototype. NOTE:
|
||||||
* if there is a this param, it will not be included.
|
* if there is a this param, it will not be included.
|
||||||
|
|
|
@ -479,7 +479,8 @@ public class RecoveredClassHelper {
|
||||||
return functionToLoadPcodeOps.get(function);
|
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()) {
|
if (vftableAddresses.isEmpty()) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
@ -3294,6 +3295,14 @@ public class RecoveredClassHelper {
|
||||||
public void addConstructorsToClassNamespace(RecoveredClass recoveredClass,
|
public void addConstructorsToClassNamespace(RecoveredClass recoveredClass,
|
||||||
Structure classStruct) throws Exception {
|
Structure classStruct) throws Exception {
|
||||||
|
|
||||||
|
DataType undefinedDT = null;
|
||||||
|
if (defaultPointerSize == 4) {
|
||||||
|
undefinedDT = new Undefined4DataType();
|
||||||
|
}
|
||||||
|
if (defaultPointerSize == 8) {
|
||||||
|
undefinedDT = new Undefined8DataType();
|
||||||
|
}
|
||||||
|
|
||||||
Namespace classNamespace = recoveredClass.getClassNamespace();
|
Namespace classNamespace = recoveredClass.getClassNamespace();
|
||||||
String className = recoveredClass.getName();
|
String className = recoveredClass.getName();
|
||||||
|
|
||||||
|
@ -3310,70 +3319,53 @@ public class RecoveredClassHelper {
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if current decompiler function return type is a pointer then set the return type
|
// commit what the decompiler knows first so that retyping will not
|
||||||
// to a pointer to the class structure, otherwise if it is a void, make it a void so the
|
// completely overwrite decompiler with listing signature
|
||||||
// listing has void too, otherwise, leave it as is, probably a void
|
decompilerUtils.commitFunction(constructorFunction);
|
||||||
String returnType = getReturnTypeFromDecompiler(constructorFunction);
|
|
||||||
|
|
||||||
// Set error bookmark, add error message, and get the listing return type if the
|
HighFunction highFunction = decompilerUtils.getHighFunction(constructorFunction);
|
||||||
// decompiler return type is null
|
if (highFunction == null) {
|
||||||
if (returnType == 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";
|
Msg.debug(this, msg + constructorFunction.getEntryPoint());
|
||||||
String msg2 = ", possibly due to the addition of class structure.";
|
|
||||||
|
|
||||||
Msg.debug(this, msg1 + " at " + constructorFunction.getEntryPoint() + msg2);
|
|
||||||
|
|
||||||
program.getBookmarkManager()
|
program.getBookmarkManager()
|
||||||
.setBookmark(constructorFunction.getEntryPoint(), BookmarkType.ERROR,
|
.setBookmark(constructorFunction.getEntryPoint(), BookmarkType.ERROR,
|
||||||
"Decompiler Error", msg1 + msg2);
|
"Decompiler Error", msg);
|
||||||
|
continue;
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnType.equals("void")) {
|
DataType returnType = highFunction.getFunctionPrototype().getReturnType();
|
||||||
constructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
if (returnType == null) {
|
||||||
|
Msg.debug(this,
|
||||||
|
"ERROR: Return type is null " + constructorFunction.getEntryPoint());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (returnType.contains("*")) {
|
|
||||||
DataType classPointerDataType = dataTypeManager.getPointer(classStruct);
|
// if a FID function and isn't void or * change it to undefined so the decompiler will
|
||||||
constructorFunction.setReturnType(classPointerDataType, SourceType.ANALYSIS);
|
|
||||||
}
|
|
||||||
// if neither and it is a FID function change it to undefined so the decompiler will
|
|
||||||
// recompute it
|
// recompute it
|
||||||
else if (isFidFunction(constructorFunction)) {
|
String returnTypeString = returnType.getDisplayName();
|
||||||
DataType undefinedDT = null;
|
if (isFidFunction(constructorFunction) && returnTypeString != "void" &&
|
||||||
if (defaultPointerSize == 4) {
|
!returnTypeString.contains("*")) {
|
||||||
undefinedDT = new Undefined4DataType();
|
|
||||||
}
|
|
||||||
if (defaultPointerSize == 8) {
|
|
||||||
undefinedDT = new Undefined8DataType();
|
|
||||||
}
|
|
||||||
if (undefinedDT != null) {
|
if (undefinedDT != null) {
|
||||||
constructorFunction.setReturnType(undefinedDT, SourceType.ANALYSIS);
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -3399,8 +3391,7 @@ public class RecoveredClassHelper {
|
||||||
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, true,
|
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, true,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
decompilerUtils.commitFunction(destructorFunction);
|
||||||
destructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3426,6 +3417,7 @@ public class RecoveredClassHelper {
|
||||||
|
|
||||||
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, false,
|
createNewSymbolAtFunction(destructorFunction, destructorName, classNamespace, false,
|
||||||
false);
|
false);
|
||||||
|
decompilerUtils.commitFunction(destructorFunction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3450,8 +3442,7 @@ public class RecoveredClassHelper {
|
||||||
createNewSymbolAtFunction(vbaseDestructorFunction, destructorName, classNamespace,
|
createNewSymbolAtFunction(vbaseDestructorFunction, destructorName, classNamespace,
|
||||||
true, true);
|
true, true);
|
||||||
}
|
}
|
||||||
|
decompilerUtils.commitFunction(vbaseDestructorFunction);
|
||||||
vbaseDestructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3606,6 +3597,7 @@ public class RecoveredClassHelper {
|
||||||
function.getEntryPoint().toString());
|
function.getEntryPoint().toString());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol = lcmd.getSymbol();
|
symbol = lcmd.getSymbol();
|
||||||
|
@ -4674,6 +4666,7 @@ public class RecoveredClassHelper {
|
||||||
createNewSymbolAtFunction(vfunction, vfunctionName, classNamespace, setPrimary,
|
createNewSymbolAtFunction(vfunction, vfunctionName, classNamespace, setPrimary,
|
||||||
removeBadFID);
|
removeBadFID);
|
||||||
}
|
}
|
||||||
|
decompilerUtils.commitFunction(vfunction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5040,6 +5033,10 @@ public class RecoveredClassHelper {
|
||||||
if (nameVfunctions) {
|
if (nameVfunctions) {
|
||||||
createNewSymbolAtFunction(indeterminateFunction,
|
createNewSymbolAtFunction(indeterminateFunction,
|
||||||
className + "_Constructor_or_Destructor", classNamespace, false, false);
|
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