Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2025-08-20 05:12:40 -04:00
commit 384d72782a
4 changed files with 62 additions and 44 deletions

View file

@ -107,6 +107,9 @@ def isNativeBinaryMakeTask(Task task, String platform) {
* *
******************************************************************************************/ ******************************************************************************************/
def shouldSkipNative(task) { def shouldSkipNative(task) {
if (rootProject.hasProperty("skipAllNatives")) {
return true;
}
return task.ext.has("skipNative") && task.ext.get("skipNative") return task.ext.has("skipNative") && task.ext.get("skipNative")
} }

View file

@ -298,16 +298,12 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
private DataType dataType; private DataType dataType;
private FieldMatcher fieldMatcher; private FieldMatcher fieldMatcher;
private String dbgPrefix;
DecompilerDataTypeFinder(DecompileResults results, Function function, DataType dataType, DecompilerDataTypeFinder(DecompileResults results, Function function, DataType dataType,
FieldMatcher fieldMatcher) { FieldMatcher fieldMatcher) {
this.decompilation = results; this.decompilation = results;
this.function = function; this.function = function;
this.dataType = dataType; this.dataType = dataType;
this.fieldMatcher = fieldMatcher; this.fieldMatcher = fieldMatcher;
this.dbgPrefix = "f: " + function + "\n\t";
} }
List<DataTypeReference> findUsage() { List<DataTypeReference> findUsage() {
@ -331,16 +327,16 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
return; return;
} }
DtrfDbg.println(dbgPrefix + "checking vars..."); DtrfDbg.println(function, "checking vars...");
List<DecompilerReference> variables = findVariableReferences(tokens); List<DecompilerReference> variables = findVariableReferences(tokens);
DtrfDbg.println(dbgPrefix + "DONE searching decompilation\nMatching results"); DtrfDbg.println(function, "DONE searching decompilation\nMatching results");
variables.forEach(v -> matchUsage(v, results)); variables.forEach(v -> matchUsage(v, results));
} }
/** Finds any search input match in the given reference */ /** Finds any search input match in the given reference */
private void matchUsage(DecompilerReference reference, List<DataTypeReference> results) { private void matchUsage(DecompilerReference reference, List<DataTypeReference> results) {
DtrfDbg.println("Checking " + reference); DtrfDbg.println(function, "Checking " + reference);
reference.accumulateMatches(dataType, fieldMatcher, results); reference.accumulateMatches(dataType, fieldMatcher, results);
} }
@ -388,12 +384,12 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
VariableAccessDR access = null; VariableAccessDR access = null;
for (ClangToken token : filteredTokens) { for (ClangToken token : filteredTokens) {
DtrfDbg.println(dbgPrefix + "checking token: " + token); DtrfDbg.println(function, "checking token: " + token);
if (token instanceof ClangTypeToken) { if (token instanceof ClangTypeToken) {
if (token.Parent() instanceof ClangReturnType) { if (token.Parent() instanceof ClangReturnType) {
DtrfDbg.println(dbgPrefix + "\treturn type: " + line); DtrfDbg.println(function, "\treturn type: " + line);
results.add(new ReturnTypeDR(line, (ClangTypeToken) token)); results.add(new ReturnTypeDR(line, (ClangTypeToken) token));
} }
@ -401,13 +397,13 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
// Note: variable refs will get their variable in an upcoming token // Note: variable refs will get their variable in an upcoming token
if (isFunctionPrototype(token.Parent())) { if (isFunctionPrototype(token.Parent())) {
DtrfDbg.println(dbgPrefix + "\tparameter: " + line); DtrfDbg.println(function, "\tparameter: " + line);
declaration = new ParameterDR(line, (ClangTypeToken) token); declaration = new ParameterDR(line, (ClangTypeToken) token);
} }
else { else {
DtrfDbg.println(dbgPrefix + "\tlocal var: " + line); DtrfDbg.println(function, "\tlocal var: " + line);
declaration = new LocalVariableDR(line, (ClangTypeToken) token); declaration = new LocalVariableDR(line, (ClangTypeToken) token);
} }
@ -416,7 +412,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
} }
else { else {
DtrfDbg.println(dbgPrefix + "\tadding a cast"); DtrfDbg.println(function, "\tadding a cast");
// Assumption: this is a cast inside of a ClangStatement // Assumption: this is a cast inside of a ClangStatement
// Assumption: there can be multiple casts concatenated // Assumption: there can be multiple casts concatenated
@ -438,7 +434,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
// //
if (declaration != null) { if (declaration != null) {
DtrfDbg.println(dbgPrefix + "\thave declaration - " + declaration); DtrfDbg.println(function, "\thave declaration - " + declaration);
declaration.setVariable((ClangVariableToken) token); declaration.setVariable((ClangVariableToken) token);
declaration = null; declaration = null;
@ -446,7 +442,7 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
else { else {
if (access == null || access.getVariable() != null) { if (access == null || access.getVariable() != null) {
DtrfDbg.println(dbgPrefix + "\tcreating variable access: " + line); DtrfDbg.println(function, "\tcreating variable access: " + line);
access = new VariableAccessDR(line); access = new VariableAccessDR(line);
results.add(access); results.add(access);
@ -479,8 +475,8 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
ClangFieldToken field = (ClangFieldToken) token; ClangFieldToken field = (ClangFieldToken) token;
if (typesDoNotMatch(access, field)) { if (typesDoNotMatch(access, field)) {
DtrfDbg.println( DtrfDbg.println(function,
dbgPrefix + "\tcreating an anonymous variable access: " + line); "\tcreating an anonymous variable access: " + line);
// 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 // after a nested array index operation

View file

@ -18,10 +18,12 @@ package ghidra.app.extension.datatype.finder;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import generic.io.NullPrintWriter; import generic.io.NullPrintWriter;
import ghidra.program.model.listing.Function;
import ghidra.util.Msg; import ghidra.util.Msg;
/** /**
@ -36,6 +38,8 @@ class DtrfDbg {
private static List<String> clientFilters = new ArrayList<>(); private static List<String> clientFilters = new ArrayList<>();
private static Map<Function, List<String>> linesByFunction = new HashMap<>();
DtrfDbg() { DtrfDbg() {
// static class // static class
} }
@ -57,6 +61,16 @@ class DtrfDbg {
return; return;
} }
Set<Entry<Function, List<String>>> entries = linesByFunction.entrySet();
for (Entry<Function, List<String>> entry : entries) {
Function function = entry.getKey();
List<String> lines = entry.getValue();
debugWriter.println("\n\nFunction Debug: " + function.getName());
for (String line : lines) {
debugWriter.println(line);
}
}
debugWriter.flush(); debugWriter.flush();
String output = debugBytes.toString(); String output = debugBytes.toString();
if (!StringUtils.isBlank(output)) { if (!StringUtils.isBlank(output)) {
@ -76,16 +90,16 @@ class DtrfDbg {
clientFilters.addAll(Arrays.asList(filters)); clientFilters.addAll(Arrays.asList(filters));
} }
static void println(String s) { static void println(Function f, String s) {
debugWriter.println(s); linesByFunction.computeIfAbsent(f, ff -> new ArrayList<>()).add(s);
} }
static void println(Object client, String s) { static void println(Function f, Object client, String s) {
if (!passesFilter(client)) { if (!passesFilter(client)) {
return; return;
} }
debugWriter.println(s); linesByFunction.computeIfAbsent(f, ff -> new ArrayList<>()).add(s);
} }
private static boolean passesFilter(Object client) { private static boolean passesFilter(Object client) {

View file

@ -105,7 +105,7 @@ public class VariableAccessDR extends DecompilerReference {
private DecompilerVariable getMatch(DataType dt, FieldMatcher fieldMatcher, private DecompilerVariable getMatch(DataType dt, FieldMatcher fieldMatcher,
DecompilerVariable var, DecompilerVariable potentialField) { DecompilerVariable var, DecompilerVariable potentialField) {
String indent = "\t\t"; String indent = "\t\t\t";
// Note: for now, I ignore the precedence of casting; if any cast type is a match, then // Note: for now, I ignore the precedence of casting; if any cast type is a match, then
// signal hooray // signal hooray
@ -113,19 +113,21 @@ public class VariableAccessDR extends DecompilerReference {
DecompilerVariable fieldVar = searchForField ? potentialField : null; DecompilerVariable fieldVar = searchForField ? potentialField : null;
DecompilerVariable match = getMatchingVarialbe(dt, var, fieldVar); DecompilerVariable match = getMatchingVarialbe(dt, var, fieldVar);
if (match == null) { if (match == null) {
DtrfDbg.println(this, indent + "NO MATCHING VARIABLE"); DtrfDbg.println(getFunction(), this, indent + "NO MATCHING VARIABLE");
return null; // wrong type, nothing to do return null; // wrong type, nothing to do
} }
// Matches on the type, does the field match? // Matches on the type, does the field match?
if (fieldMatcher.isIgnored()) { if (fieldMatcher.isIgnored()) {
DtrfDbg.println(this, indent + "field macher is ignored; returning match"); DtrfDbg.println(getFunction(), this,
indent + "field macher is ignored; returning match");
return match; // no field to match return match; // no field to match
} }
if (potentialField == null) { if (potentialField == null) {
DtrfDbg.println(this, indent + "No potential field to match; name / offset match?"); DtrfDbg.println(getFunction(), this,
indent + "No potential field to match; name / offset match?");
// check for the case where we have not been passed a 'potential field', but the given // check for the case where we have not been passed a 'potential field', but the given
// 'var' is itself may be the field we seek, such as in an if statement like this: // 'var' is itself may be the field we seek, such as in an if statement like this:
@ -134,23 +136,25 @@ public class VariableAccessDR extends DecompilerReference {
String name = var.getName(); String name = var.getName();
int offset = var.getOffset(); int offset = var.getOffset();
if (fieldMatcher.matches(name, offset)) { if (fieldMatcher.matches(name, offset)) {
DtrfDbg.println(this, indent + "\tfield matcher matched on variable: " + var); StringUtilities.indentLines(var.toString(), indent + '\t');
DtrfDbg.println(getFunction(), this,
indent + "\tfield matcher matched on variable: " + var);
return var; return var;
} }
DtrfDbg.println(this, indent + "\tNO FIELD MATCHER MATCH"); DtrfDbg.println(getFunction(), this, indent + "\tNO FIELD MATCHER MATCH");
return null; // we seek a field, but there is none return null; // we seek a field, but there is none
} }
DtrfDbg.println(this, indent + "Checking 'potential field' match..."); DtrfDbg.println(getFunction(), this, indent + "Checking 'potential field' match...");
String name = potentialField.getName(); String name = potentialField.getName();
int offset = potentialField.getOffset(); int offset = potentialField.getOffset();
if (fieldMatcher.matches(name, offset)) { if (fieldMatcher.matches(name, offset)) {
DtrfDbg.println(this, indent + "\tMATCHED"); DtrfDbg.println(getFunction(), this, indent + "\tMATCHED");
return match; return match;
} }
DtrfDbg.println(this, indent + "\tNO MATCH"); DtrfDbg.println(getFunction(), this, indent + "\tNO MATCH");
return null; return null;
} }
@ -159,26 +163,27 @@ public class VariableAccessDR extends DecompilerReference {
String indent = "\t\t\t"; String indent = "\t\t\t";
DtrfDbg.println(this, indent + "Checking for matching variable; any casts?"); DtrfDbg.println(getFunction(), this, indent + "Checking for matching variable; any casts?");
List<DecompilerVariable> castVariables = var.getCasts(); List<DecompilerVariable> castVariables = var.getCasts();
for (DecompilerVariable cast : castVariables) { for (DecompilerVariable cast : castVariables) {
if (matchesType(cast, dt)) { if (matchesType(cast, dt)) {
DtrfDbg.println(this, indent + "MATCHED cast: " + cast); DtrfDbg.println(getFunction(), this, indent + "MATCHED cast: " + cast);
return cast; return cast;
} }
} }
String dtString = dt == null ? "null" : dt.toString(); String dtString = dt == null ? "null" : dt.toString();
DtrfDbg.println(this, DtrfDbg.println(getFunction(), this,
indent + "No matched casts; checking type against var:\n" + indent + "No matched casts; checking type against var:\n" +
StringUtilities.indentLines("type: " + dtString, indent + "\t") + "\n" + StringUtilities.indentLines("type: " + dtString, indent + "\t") + "\n" +
StringUtilities.indentLines("var: " + var.toString(), indent + "\t")); StringUtilities.indentLines("var: " + var.toString(), indent + "\t"));
if (matchesType(var, dt)) { if (matchesType(var, dt)) {
DtrfDbg.println(this, indent + "MATCHED type: "); DtrfDbg.println(getFunction(), this, indent + "MATCHED type: ");
return var; return var;
} }
DtrfDbg.println(this, indent + "Type did not match; checking High Variable: "); DtrfDbg.println(getFunction(), this,
indent + "Type did not match; checking High Variable: ");
// //
// Unusual Code Alert! // Unusual Code Alert!
@ -193,12 +198,12 @@ public class VariableAccessDR extends DecompilerReference {
HighVariable highVariable = var.variable.getHighVariable(); HighVariable highVariable = var.variable.getHighVariable();
if (highVariable != null) { if (highVariable != null) {
if (matchesParentType(potentialField, dt)) { if (matchesParentType(potentialField, dt)) {
DtrfDbg.println(this, indent + "MATCHED on parent type: " + dt); DtrfDbg.println(getFunction(), this, indent + "MATCHED on parent type: " + dt);
return potentialField; return potentialField;
} }
} }
DtrfDbg.println(this, indent + "NOT MATCHED"); DtrfDbg.println(getFunction(), this, indent + "NOT MATCHED");
return null; return null;
} }
@ -217,7 +222,7 @@ public class VariableAccessDR extends DecompilerReference {
String indent = "\t\t\t\t"; String indent = "\t\t\t\t";
if (var == null) { if (var == null) {
DtrfDbg.println(this, indent + "Types Match? no variable to check"); DtrfDbg.println(getFunction(), this, indent + "Types Match? no variable to check");
return false; return false;
} }
@ -225,7 +230,7 @@ public class VariableAccessDR extends DecompilerReference {
if (varType == null) { if (varType == null) {
// it seems odd to me that there is no type, but I have seen this in the case // it seems odd to me that there is no type, but I have seen this in the case
// statement of a switch // statement of a switch
DtrfDbg.println(this, indent + "ypes Match? no variable TYPE to check"); DtrfDbg.println(getFunction(), this, indent + "ypes Match? no variable TYPE to check");
return false; return false;
} }
boolean matches = isEqual(varType, dt); boolean matches = isEqual(varType, dt);