mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1514 - Find References to - Added support for finding usage of enum
fields Closes #1967
This commit is contained in:
parent
2fb860bcd7
commit
33b2bbbd0b
15 changed files with 108 additions and 135 deletions
|
@ -31,7 +31,8 @@ import ghidra.app.plugin.core.navigation.locationreferences.ReferenceUtils;
|
|||
import ghidra.app.services.DataTypeReference;
|
||||
import ghidra.app.services.DataTypeReferenceFinder;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.BuiltInDataType;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.StringUtilities;
|
||||
|
@ -40,7 +41,7 @@ import ghidra.util.exception.CancelledException;
|
|||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Implementation of {@link DataTypeReferenceFinder} that uses the Decompiler's output
|
||||
* Implementation of {@link DataTypeReferenceFinder} that uses the Decompiler's output
|
||||
* to find data type and composite field usage.
|
||||
*/
|
||||
public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinder {
|
||||
|
@ -52,29 +53,11 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
@Override
|
||||
public void findReferences(Program program, DataType dataType,
|
||||
Consumer<DataTypeReference> callback, TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
DecompilerDataTypeFinderQCallback qCallback =
|
||||
new DecompilerDataTypeFinderQCallback(program, dataType, callback);
|
||||
|
||||
Set<Function> functions = filterFunctions(program, dataType, monitor);
|
||||
|
||||
try {
|
||||
ParallelDecompiler.decompileFunctions(qCallback, functions, monitor);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt(); // reset the flag
|
||||
Msg.trace(this, "Interrupted while decompiling functions");
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Encountered an exception decompiling functions", e);
|
||||
}
|
||||
finally {
|
||||
qCallback.dispose();
|
||||
}
|
||||
findReferences(program, dataType, null, callback, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findReferences(Program program, Composite dataType, String fieldName,
|
||||
public void findReferences(Program program, DataType dataType, String fieldName,
|
||||
Consumer<DataTypeReference> callback, TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
DecompilerDataTypeFinderQCallback qCallback =
|
||||
|
@ -175,12 +158,12 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
|
||||
// We have a different type, should we search for it?
|
||||
if (baseType instanceof BuiltInDataType) {
|
||||
// When given a wrapper type (e.g., typedef) , ignore
|
||||
// built-ins (e.g., int, byte, etc), as
|
||||
// When given a wrapper type (e.g., typedef) , ignore
|
||||
// built-ins (e.g., int, byte, etc), as
|
||||
// they will be of little value due to their volume in the program and the
|
||||
// user *probably* did not intend to search for them. (Below we do not do
|
||||
// this check, which allows the user to search directly for a
|
||||
// built-in type, if they wish.)
|
||||
// user *probably* did not intend to search for them. (Below we do not do
|
||||
// this check, which allows the user to search directly for a
|
||||
// built-in type, if they wish.)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -227,12 +210,6 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
private DataType dataType;
|
||||
private String fieldName;
|
||||
|
||||
/* Search for Data Type access only--no field usage */
|
||||
DecompilerDataTypeFinderQCallback(Program program, DataType dataType,
|
||||
Consumer<DataTypeReference> callback) {
|
||||
this(program, dataType, null, callback);
|
||||
}
|
||||
|
||||
/* Search for composite field access */
|
||||
DecompilerDataTypeFinderQCallback(Program program, DataType dataType, String fieldName,
|
||||
Consumer<DataTypeReference> callback) {
|
||||
|
@ -279,7 +256,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
}
|
||||
|
||||
/**
|
||||
* Class to do the work of searching through the Decompiler's results for the desired
|
||||
* Class to do the work of searching through the Decompiler's results for the desired
|
||||
* data type access.
|
||||
*/
|
||||
private static class DecompilerDataTypeFinder {
|
||||
|
@ -308,7 +285,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
|
||||
ClangTokenGroup tokens = decompilation.getCCodeMarkup();
|
||||
|
||||
// TODO delete this when the ticket settles down
|
||||
// TODO delete this when the ticket settles down
|
||||
// dumpTokens(tokens, 0);
|
||||
// dumpTokenNames(tokens, 0);
|
||||
|
||||
|
@ -339,15 +316,15 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
}
|
||||
|
||||
/**
|
||||
* Uses the given line to find variables (also parameters and return types) and any
|
||||
* accesses to them in that line. A given variable may be used directly or, as in
|
||||
* Uses the given line to find variables (also parameters and return types) and any
|
||||
* accesses to them in that line. A given variable may be used directly or, as in
|
||||
* the case with Composite types, may have one of its fields accessed. Each result
|
||||
* found by this method will be at least a variable access and may also itself have
|
||||
* field accesses.
|
||||
*
|
||||
* <p>Sometimes a line is structured such that there are anonymous variable accesses. This
|
||||
* is the case where a Composite is being accessed, but the Composite itself is
|
||||
* not a variable in the current function. See {@link AnonymousVariableAccessDR} for
|
||||
* not a variable in the current function. See {@link AnonymousVariableAccessDR} for
|
||||
* more details.
|
||||
*
|
||||
* @param line the current line being processed from the Decompiler
|
||||
|
@ -396,14 +373,14 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
else if (token instanceof ClangVariableToken) {
|
||||
|
||||
//
|
||||
// Observations:
|
||||
// 1) 'access' will be null if we are on a C statement that
|
||||
// is a declaration (parameter or variable). In this case,
|
||||
// Observations:
|
||||
// 1) 'access' will be null if we are on a C statement that
|
||||
// is a declaration (parameter or variable). In this case,
|
||||
// 'declaration' will be an instance of VariableDR.
|
||||
// 2) 'access' will be null the first time a variable is used in
|
||||
// a statement.
|
||||
// 3) if 'access' is non-null, but already has a variable assigned,
|
||||
// then this means the current ClangVariableToken represents a new
|
||||
// 3) if 'access' is non-null, but already has a variable assigned,
|
||||
// then this means the current ClangVariableToken represents a new
|
||||
// variable access/usage.
|
||||
//
|
||||
if (declaration != null) {
|
||||
|
@ -427,7 +404,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
|
||||
if (access == null) {
|
||||
// Uh-oh. I've only seen this when line-wrapping is happening. In that
|
||||
// case, try to get the last variable that we've seen and assume that
|
||||
// case, try to get the last variable that we've seen and assume that
|
||||
// is the variable to which this field belongs.
|
||||
access = getLastAccess(results);
|
||||
if (access == null) {
|
||||
|
@ -442,7 +419,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
|||
|
||||
ClangFieldToken field = (ClangFieldToken) token;
|
||||
if (typesDoNotMatch(access, field)) {
|
||||
// this can happen when a field is used anonymously, such as directly
|
||||
// this can happen when a field is used anonymously, such as directly
|
||||
// after a nested array index operation
|
||||
results.add(new AnonymousVariableAccessDR(line, field));
|
||||
continue;
|
||||
|
|
|
@ -174,7 +174,7 @@ public abstract class DecompilerReference {
|
|||
return "{\n" +
|
||||
"\tvariable: " + StringUtilities.toStringWithIndent(variable) + ",\n" +
|
||||
"\tdata type: " + getDataType() + ",\n"+
|
||||
"\tline " + getContext() + ",\n" +
|
||||
"\tline " + StringUtilities.toStringWithIndent(getContext().getPlainText()) + ",\n" +
|
||||
"\tfunction: " + getFunction() + "\n" +
|
||||
"}";
|
||||
//@formatter:on
|
||||
|
|
|
@ -120,6 +120,16 @@ public class VariableAccessDR extends DecompilerReference {
|
|||
}
|
||||
|
||||
if (potentialField == null) {
|
||||
|
||||
// check for the case where we have not been passed a 'potential field', but the given
|
||||
// 'var' is itself the field we seek, such as in an if statement like this:
|
||||
// if (color == RED)
|
||||
// where 'RED' is the variable we are checking
|
||||
String name = var.getName();
|
||||
if (fieldName.equals(name)) {
|
||||
return var;
|
||||
}
|
||||
|
||||
return null; // we seek a field, but there is none
|
||||
}
|
||||
|
||||
|
@ -268,7 +278,7 @@ public class VariableAccessDR extends DecompilerReference {
|
|||
|
||||
//@formatter:off
|
||||
return "{\n" +
|
||||
"\tline " + getContext() + ",\n" +
|
||||
"\tline " + getContext().getPlainText() + ",\n" +
|
||||
"\tfunction: " + getFunction() + "\n" +
|
||||
"\tvariable: " + StringUtilities.toStringWithIndent(variable) + ",\n" +
|
||||
"\tdata type: " + getDataType() + ",\n"+
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue