mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1421 - Version Tracking - Converted 'command' to a 'task' and updated
the progress monitor to show continuous progress; fixed slow test Closes #3221
This commit is contained in:
parent
e55550edfd
commit
c3375b6b88
8 changed files with 334 additions and 246 deletions
|
@ -32,9 +32,3 @@ dependencies {
|
||||||
testImplementation "org.jmockit:jmockit:1.44"
|
testImplementation "org.jmockit:jmockit:1.44"
|
||||||
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
||||||
}
|
}
|
||||||
integrationTest {
|
|
||||||
// tests to slow to run during automated testing
|
|
||||||
excludes = [
|
|
||||||
'**/VTAutoVersionTrackingTest*',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,12 +23,13 @@ import java.util.List;
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.feature.vt.api.db.VTSessionDB;
|
import ghidra.feature.vt.api.db.VTSessionDB;
|
||||||
import ghidra.feature.vt.api.main.VTSession;
|
import ghidra.feature.vt.api.main.VTSession;
|
||||||
import ghidra.feature.vt.gui.actions.AutoVersionTrackingCommand;
|
import ghidra.feature.vt.gui.actions.AutoVersionTrackingTask;
|
||||||
import ghidra.feature.vt.gui.plugin.*;
|
import ghidra.feature.vt.gui.plugin.*;
|
||||||
import ghidra.framework.model.DomainFolder;
|
import ghidra.framework.model.DomainFolder;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.util.task.TaskLauncher;
|
||||||
|
|
||||||
public class AutoVersionTrackingScript extends GhidraScript {
|
public class AutoVersionTrackingScript extends GhidraScript {
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,15 +73,10 @@ public class AutoVersionTrackingScript extends GhidraScript {
|
||||||
|
|
||||||
//String description = "AutoVTScript";
|
//String description = "AutoVTScript";
|
||||||
|
|
||||||
AutoVersionTrackingCommand autoVTcmd =
|
AutoVersionTrackingTask autoVtTask =
|
||||||
new AutoVersionTrackingCommand(controller, session, 1.0, 10.0);
|
new AutoVersionTrackingTask(controller, session, 1.0, 10.0);
|
||||||
|
|
||||||
controller.getTool().executeBackgroundCommand(autoVTcmd, session);
|
|
||||||
//destinationProgram.save(description, monitor);
|
|
||||||
|
|
||||||
//session.save(description, monitor);
|
|
||||||
//session.release(this);
|
|
||||||
|
|
||||||
|
TaskLauncher.launch(autoVtTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Plugin> T getPlugin(PluginTool tool, Class<T> c) {
|
public static <T extends Plugin> T getPlugin(PluginTool tool, Class<T> c) {
|
||||||
|
|
|
@ -25,10 +25,11 @@ import ghidra.feature.vt.gui.plugin.VTController;
|
||||||
import ghidra.feature.vt.gui.plugin.VTPlugin;
|
import ghidra.feature.vt.gui.plugin.VTPlugin;
|
||||||
import ghidra.util.HTMLUtilities;
|
import ghidra.util.HTMLUtilities;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
import ghidra.util.task.TaskLauncher;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This action runs the {@link AutoVersionTrackingCommand}
|
* This action runs the {@link AutoVersionTrackingTask}
|
||||||
*/
|
*/
|
||||||
public class AutoVersionTrackingAction extends DockingAction {
|
public class AutoVersionTrackingAction extends DockingAction {
|
||||||
public static Icon AUTO_VT_ICON = ResourceManager.loadImage("images/wizard.png");
|
public static Icon AUTO_VT_ICON = ResourceManager.loadImage("images/wizard.png");
|
||||||
|
@ -59,18 +60,16 @@ public class AutoVersionTrackingAction extends DockingAction {
|
||||||
|
|
||||||
VTSession session = controller.getSession();
|
VTSession session = controller.getSession();
|
||||||
|
|
||||||
// In the future we might want to make these user options so the user can change them
|
// In the future we might want to make these user options so the user can change them.
|
||||||
// I don't want to make this change until the confidence option in the reference
|
// We don't want to make this change until the confidence option in the reference
|
||||||
// correlators is changed to make more sense to the user - currently the confidence has
|
// correlators is changed to make more sense to the user - currently the confidence has
|
||||||
// to be entered as the value before the log 10 is computed but the table shows log 10 value
|
// to be entered as the value before the log 10 is computed but the table shows log 10 value.
|
||||||
|
//
|
||||||
// The current passed values for score and confidence (.95 and 10.0)
|
// The current passed values for score and confidence (.95 and 10.0)
|
||||||
// get you accepted matches with similarity scores >= .95 and
|
// get you accepted matches with similarity scores >= .95 and
|
||||||
// confidence (log 10) scores 2.0 and up
|
// confidence (log 10) scores 2.0 and up
|
||||||
AutoVersionTrackingCommand command =
|
AutoVersionTrackingTask task = new AutoVersionTrackingTask(controller, session, 0.95, 10.0);
|
||||||
new AutoVersionTrackingCommand(controller, session, 0.95, 10.0);
|
TaskLauncher.launch(task);
|
||||||
|
|
||||||
controller.getTool().executeBackgroundCommand(command, session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.feature.vt.gui.actions;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
import ghidra.feature.vt.api.correlator.program.*;
|
import ghidra.feature.vt.api.correlator.program.*;
|
||||||
import ghidra.feature.vt.api.main.*;
|
import ghidra.feature.vt.api.main.*;
|
||||||
import ghidra.feature.vt.api.util.VTAssociationStatusException;
|
import ghidra.feature.vt.api.util.VTAssociationStatusException;
|
||||||
|
@ -24,8 +26,6 @@ import ghidra.feature.vt.api.util.VTOptions;
|
||||||
import ghidra.feature.vt.gui.plugin.VTController;
|
import ghidra.feature.vt.gui.plugin.VTController;
|
||||||
import ghidra.feature.vt.gui.task.ApplyMarkupItemTask;
|
import ghidra.feature.vt.gui.task.ApplyMarkupItemTask;
|
||||||
import ghidra.feature.vt.gui.util.MatchInfo;
|
import ghidra.feature.vt.gui.util.MatchInfo;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
@ -36,12 +36,12 @@ import ghidra.program.util.ListingDiff;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.*;
|
||||||
import util.CollectionUtils;
|
import util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This command runs all of the <b>exact</b> {@link VTProgramCorrelator}s that return
|
* This command runs all of the <b>exact</b> {@link VTProgramCorrelator}s that return
|
||||||
* unique matches (ie only one of each match is found in each program):
|
* unique matches (i.e., only one of each match is found in each program):
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li> Exact Symbol Name correlator </li>
|
* <li> Exact Symbol Name correlator </li>
|
||||||
* <li> Exact Data correlator </li>
|
* <li> Exact Data correlator </li>
|
||||||
|
@ -65,8 +65,9 @@ import util.CollectionUtils;
|
||||||
* <P> As more techniques get developed, more automation will be added to this command.
|
* <P> As more techniques get developed, more automation will be added to this command.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AutoVersionTrackingCommand extends BackgroundCommand {
|
public class AutoVersionTrackingTask extends Task {
|
||||||
|
|
||||||
|
private static final String NAME = "Auto Version Tracking Command";
|
||||||
private VTSession session;
|
private VTSession session;
|
||||||
private Program sourceProgram;
|
private Program sourceProgram;
|
||||||
private Program destinationProgram;
|
private Program destinationProgram;
|
||||||
|
@ -78,7 +79,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
private double minCombinedReferenceCorrelatorConfidence;
|
private double minCombinedReferenceCorrelatorConfidence;
|
||||||
private final ToolOptions applyOptions;
|
private final ToolOptions applyOptions;
|
||||||
private String statusMsg = null;
|
private String statusMsg = null;
|
||||||
private static int NUM_CORRELATORS = 7;
|
private static int NUM_CORRELATORS = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for AutoVersionTrackingCommand
|
* Constructor for AutoVersionTrackingCommand
|
||||||
|
@ -92,9 +93,10 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
* @param minCombinedReferenceCorrelatorConfidence The minimum confidence used to limit matches
|
* @param minCombinedReferenceCorrelatorConfidence The minimum confidence used to limit matches
|
||||||
* created by the Combined Reference Correlator.
|
* created by the Combined Reference Correlator.
|
||||||
*/
|
*/
|
||||||
public AutoVersionTrackingCommand(VTController controller, VTSession session,
|
public AutoVersionTrackingTask(VTController controller, VTSession session,
|
||||||
double minCombinedReferenceCorrelatorScore,
|
double minCombinedReferenceCorrelatorScore,
|
||||||
double minCombinedReferenceCorrelatorConfidence) {
|
double minCombinedReferenceCorrelatorConfidence) {
|
||||||
|
super(NAME, true, true, true);
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.sourceProgram = session.getSourceProgram();
|
this.sourceProgram = session.getSourceProgram();
|
||||||
this.destinationProgram = session.getDestinationProgram();
|
this.destinationProgram = session.getDestinationProgram();
|
||||||
|
@ -103,45 +105,85 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
this.minCombinedReferenceCorrelatorScore = minCombinedReferenceCorrelatorScore;
|
this.minCombinedReferenceCorrelatorScore = minCombinedReferenceCorrelatorScore;
|
||||||
this.minCombinedReferenceCorrelatorConfidence = minCombinedReferenceCorrelatorConfidence;
|
this.minCombinedReferenceCorrelatorConfidence = minCombinedReferenceCorrelatorConfidence;
|
||||||
this.applyOptions = controller.getOptions();
|
this.applyOptions = controller.getOptions();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public int getStatusTextAlignment() {
|
||||||
|
return SwingConstants.LEADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(TaskMonitor monitor) throws CancelledException {
|
||||||
|
|
||||||
|
boolean error = true;
|
||||||
|
int id = session.startTransaction(NAME);
|
||||||
|
try {
|
||||||
|
session.setEventsEnabled(false);
|
||||||
|
doRun(monitor);
|
||||||
|
error = false;
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
error = false; // allow work performed so far to be saved
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
session.setEventsEnabled(true);
|
||||||
|
session.endTransaction(id, !error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRun(TaskMonitor realMonitor) throws CancelledException {
|
||||||
|
|
||||||
|
SubTaskMonitor monitor = new SubTaskMonitor(realMonitor);
|
||||||
|
|
||||||
boolean hasApplyErrors = false;
|
boolean hasApplyErrors = false;
|
||||||
sourceAddressSet = sourceProgram.getMemory().getLoadedAndInitializedAddressSet();
|
sourceAddressSet = sourceProgram.getMemory().getLoadedAndInitializedAddressSet();
|
||||||
destinationAddressSet = destinationProgram.getMemory().getLoadedAndInitializedAddressSet();
|
destinationAddressSet = destinationProgram.getMemory().getLoadedAndInitializedAddressSet();
|
||||||
try {
|
|
||||||
monitor.setMessage("Running Auto Version Tracking");
|
|
||||||
monitor.setCancelEnabled(true);
|
|
||||||
monitor.initialize(NUM_CORRELATORS);
|
|
||||||
|
|
||||||
// Use default options for all of the "exact" correlators and passed in options for
|
int count = 0;
|
||||||
// the others.
|
monitor.doInitialize(NUM_CORRELATORS);
|
||||||
|
|
||||||
|
// Use default options for all of the "exact" correlators; passed in options for the others
|
||||||
VTOptions options;
|
VTOptions options;
|
||||||
|
|
||||||
// Run the correlators in the following order:
|
// Run the correlators in the following order:
|
||||||
// Do this one first because we don't want it to find ones that get markup
|
// Do this one first because we don't want it to find ones that get markup applied by later
|
||||||
// applied by later correlators
|
// correlators
|
||||||
VTProgramCorrelatorFactory factory = new SymbolNameProgramCorrelatorFactory();
|
VTProgramCorrelatorFactory factory = new SymbolNameProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
|
|
||||||
|
String prefix = "%s correlation (%d of " + NUM_CORRELATORS + ") - ";
|
||||||
|
monitor.setPrefix(String.format(prefix, "Symbol Name", ++count));
|
||||||
hasApplyErrors = correlateAndPossiblyApply(factory, options, monitor);
|
hasApplyErrors = correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
factory = new ExactDataMatchProgramCorrelatorFactory();
|
factory = new ExactDataMatchProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
|
|
||||||
|
monitor.setPrefix(String.format(prefix, "Exact Data", ++count));
|
||||||
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
factory = new ExactMatchBytesProgramCorrelatorFactory();
|
factory = new ExactMatchBytesProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
|
|
||||||
|
monitor.setPrefix(String.format(prefix, "Exact Bytes", ++count));
|
||||||
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
factory = new ExactMatchInstructionsProgramCorrelatorFactory();
|
factory = new ExactMatchInstructionsProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
|
|
||||||
|
monitor.setPrefix(String.format(prefix, "Exact Instructions", ++count));
|
||||||
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
factory = new ExactMatchMnemonicsProgramCorrelatorFactory();
|
factory = new ExactMatchMnemonicsProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
|
|
||||||
|
monitor.setPrefix(String.format(prefix, "Exact Mnemonic", ++count));
|
||||||
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
hasApplyErrors |= correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
// This is the first of the "speculative" post-correlator match algorithm. The correlator
|
// This is the first of the "speculative" post-correlator match algorithm. The correlator
|
||||||
// returns all duplicate function instruction matches so there will always be more
|
// returns all duplicate function instruction matches so there will always be more
|
||||||
|
@ -152,19 +194,19 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
// finding the correct match is very accurate.
|
// finding the correct match is very accurate.
|
||||||
factory = new DuplicateFunctionMatchProgramCorrelatorFactory();
|
factory = new DuplicateFunctionMatchProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
hasApplyErrors |=
|
|
||||||
correlateAndPossiblyApplyDuplicateFunctions(factory, options, monitor);
|
monitor.setPrefix(String.format(prefix, "Duplicate Function", ++count));
|
||||||
|
hasApplyErrors |= correlateAndPossiblyApplyDuplicateFunctions(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
// The rest are mores speculative matching algorithms because they depend on our
|
// The rest are mores speculative matching algorithms because they depend on our
|
||||||
// choosing the correct score/confidence pair to determine very probable matches. These
|
// choosing the correct score/confidence pair to determine very probable matches. These
|
||||||
// values were chosen based on what has been seen so far but this needs to be tested
|
// values were chosen based on what has been seen so far but this needs to be tested
|
||||||
// further on more programs and possibly add options for users to
|
// further on more programs and possibly add options for users to give their own thresholds.
|
||||||
// give their own thresholds.
|
|
||||||
|
|
||||||
// Get the names of the confidence and similarity score thresholds that
|
// Get the names of the confidence and similarity score thresholds that
|
||||||
// are used by all of the "reference" correlators
|
// are used by all of the "reference" correlators
|
||||||
String confidenceOption =
|
String confidenceOption = VTAbstractReferenceProgramCorrelatorFactory.CONFIDENCE_THRESHOLD;
|
||||||
VTAbstractReferenceProgramCorrelatorFactory.CONFIDENCE_THRESHOLD;
|
|
||||||
String scoreOption = VTAbstractReferenceProgramCorrelatorFactory.SIMILARITY_THRESHOLD;
|
String scoreOption = VTAbstractReferenceProgramCorrelatorFactory.SIMILARITY_THRESHOLD;
|
||||||
|
|
||||||
// Get the number of data and function matches
|
// Get the number of data and function matches
|
||||||
|
@ -178,44 +220,45 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
options.setDouble(confidenceOption, minCombinedReferenceCorrelatorConfidence);
|
options.setDouble(confidenceOption, minCombinedReferenceCorrelatorConfidence);
|
||||||
options.setDouble(scoreOption, minCombinedReferenceCorrelatorScore);
|
options.setDouble(scoreOption, minCombinedReferenceCorrelatorScore);
|
||||||
hasApplyErrors =
|
|
||||||
hasApplyErrors | correlateAndPossiblyApply(factory, options, monitor);
|
monitor.setPrefix(String.format(prefix, "Data Reference", ++count));
|
||||||
|
hasApplyErrors = hasApplyErrors | correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
// Get the number of data and function matches again if this correlator ran
|
// Get the number of data and function matches again if this correlator ran
|
||||||
numDataMatches = getNumberOfDataMatches(monitor);
|
numDataMatches = getNumberOfDataMatches(monitor);
|
||||||
numFunctionMatches = getNumberOfFunctionMatches(monitor);
|
numFunctionMatches = getNumberOfFunctionMatches(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the FunctionReferenceCorrelator if there are accepted function matches but
|
// Run the FunctionReferenceCorrelator if there are accepted function matches but no
|
||||||
// no accepted data matches
|
// accepted data matches
|
||||||
if (numDataMatches > 0 && numFunctionMatches == 0) {
|
if (numDataMatches > 0 && numFunctionMatches == 0) {
|
||||||
factory = new FunctionReferenceProgramCorrelatorFactory();
|
factory = new FunctionReferenceProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
options.setDouble(confidenceOption, minCombinedReferenceCorrelatorConfidence);
|
options.setDouble(confidenceOption, minCombinedReferenceCorrelatorConfidence);
|
||||||
options.setDouble(scoreOption, minCombinedReferenceCorrelatorScore);
|
options.setDouble(scoreOption, minCombinedReferenceCorrelatorScore);
|
||||||
factory = new FunctionReferenceProgramCorrelatorFactory();
|
factory = new FunctionReferenceProgramCorrelatorFactory();
|
||||||
hasApplyErrors =
|
|
||||||
hasApplyErrors | correlateAndPossiblyApply(factory, options, monitor);
|
monitor.setPrefix(String.format(prefix, "Function Reference", ++count));
|
||||||
|
hasApplyErrors = hasApplyErrors | correlateAndPossiblyApply(factory, options, monitor);
|
||||||
|
monitor.doIncrementProgress();
|
||||||
|
|
||||||
// Get the number of data and function matches again if this correlator ran
|
// Get the number of data and function matches again if this correlator ran
|
||||||
numDataMatches = getNumberOfDataMatches(monitor);
|
numDataMatches = getNumberOfDataMatches(monitor);
|
||||||
numFunctionMatches = getNumberOfFunctionMatches(monitor);
|
numFunctionMatches = getNumberOfFunctionMatches(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the CombinedDataAndFunctionReferenceCorrelator if there are both accepted function matches but
|
// Run the CombinedDataAndFunctionReferenceCorrelator if there are both accepted function
|
||||||
// and data matches
|
// matches but and data matches
|
||||||
if (numDataMatches > 0 && numFunctionMatches > 0) {
|
if (numDataMatches > 0 && numFunctionMatches > 0) {
|
||||||
factory = new CombinedFunctionAndDataReferenceProgramCorrelatorFactory();
|
factory = new CombinedFunctionAndDataReferenceProgramCorrelatorFactory();
|
||||||
options = factory.createDefaultOptions();
|
options = factory.createDefaultOptions();
|
||||||
options.setDouble(confidenceOption, minCombinedReferenceCorrelatorConfidence);
|
options.setDouble(confidenceOption, minCombinedReferenceCorrelatorConfidence);
|
||||||
options.setDouble(scoreOption, minCombinedReferenceCorrelatorScore);
|
options.setDouble(scoreOption, minCombinedReferenceCorrelatorScore);
|
||||||
hasApplyErrors =
|
|
||||||
hasApplyErrors | correlateAndPossiblyApply(factory, options, monitor);
|
monitor.setPrefix(String.format(prefix, "Function and Data", ++count));
|
||||||
}
|
hasApplyErrors = hasApplyErrors | correlateAndPossiblyApply(factory, options, monitor);
|
||||||
}
|
monitor.doIncrementProgress();
|
||||||
catch (CancelledException e) {
|
|
||||||
statusMsg = getName() + " was cancelled.";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String applyMarkupStatus = " with no apply markup errors.";
|
String applyMarkupStatus = " with no apply markup errors.";
|
||||||
|
@ -223,13 +266,9 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
applyMarkupStatus =
|
applyMarkupStatus =
|
||||||
" with some apply markup errors. See the log or the markup table for more details";
|
" with some apply markup errors. See the log or the markup table for more details";
|
||||||
}
|
}
|
||||||
statusMsg =
|
statusMsg = NAME + " completed successfully" + applyMarkupStatus;
|
||||||
|
|
||||||
getName() + " completed successfully" + applyMarkupStatus;
|
|
||||||
|
|
||||||
controller.getTool().setStatusInfo(statusMsg);
|
controller.getTool().setStatusInfo(statusMsg);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getNumberOfDataMatches(TaskMonitor monitor) throws CancelledException {
|
private int getNumberOfDataMatches(TaskMonitor monitor) throws CancelledException {
|
||||||
|
@ -288,7 +327,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
sourceAddressSet, destinationProgram, destinationAddressSet, options);
|
sourceAddressSet, destinationProgram, destinationAddressSet, options);
|
||||||
|
|
||||||
VTMatchSet results = correlator.correlate(session, monitor);
|
VTMatchSet results = correlator.correlate(session, monitor);
|
||||||
|
monitor.initialize(results.getMatchCount());
|
||||||
boolean hasMarkupErrors = applyMatches(results.getMatches(), correlator.getName(), monitor);
|
boolean hasMarkupErrors = applyMatches(results.getMatches(), correlator.getName(), monitor);
|
||||||
|
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
|
@ -318,6 +357,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
sourceAddressSet, destinationProgram, destinationAddressSet, options);
|
sourceAddressSet, destinationProgram, destinationAddressSet, options);
|
||||||
|
|
||||||
VTMatchSet results = correlator.correlate(session, monitor);
|
VTMatchSet results = correlator.correlate(session, monitor);
|
||||||
|
monitor.initialize(results.getMatchCount());
|
||||||
boolean hasMarkupErrors = applyDuplicateFunctionMatches(results.getMatches(), monitor);
|
boolean hasMarkupErrors = applyDuplicateFunctionMatches(results.getMatches(), monitor);
|
||||||
|
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
|
@ -363,6 +403,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
|
|
||||||
ApplyMarkupItemTask markupTask =
|
ApplyMarkupItemTask markupTask =
|
||||||
new ApplyMarkupItemTask(controller.getSession(), markupItems, applyOptions);
|
new ApplyMarkupItemTask(controller.getSession(), markupItems, applyOptions);
|
||||||
|
|
||||||
markupTask.run(monitor);
|
markupTask.run(monitor);
|
||||||
boolean currentMatchHasErrors = markupTask.hasErrors();
|
boolean currentMatchHasErrors = markupTask.hasErrors();
|
||||||
if (currentMatchHasErrors) {
|
if (currentMatchHasErrors) {
|
||||||
|
@ -387,19 +428,19 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (VTAssociationStatusException e) {
|
catch (VTAssociationStatusException e) {
|
||||||
Msg.warn(AutoVersionTrackingCommand.class,
|
Msg.warn(AutoVersionTrackingTask.class,
|
||||||
"Could not set match accepted for " + association, e);
|
"Could not set match accepted for " + association, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept matches and apply markup for duplicate function instruction matches with matching operands
|
* Accept matches and apply markup for duplicate function instruction matches with matching
|
||||||
* if they are a unique match within their associated set.
|
* operands if they are a unique match within their associated set.
|
||||||
* @param matches A collection of version tracking matches from the duplicate instruction
|
* @param matches A collection of version tracking matches from the duplicate instruction
|
||||||
* matcher.
|
* matcher
|
||||||
* @param monitor Allows user to cancel
|
* @param monitor Allows user to cancel
|
||||||
* @return true if any markup errors, false if no markup errors.
|
* @return true if any markup errors, false if no markup errors
|
||||||
* @throws CancelledException if cancelled
|
* @throws CancelledException if cancelled
|
||||||
*/
|
*/
|
||||||
private boolean applyDuplicateFunctionMatches(Collection<VTMatch> matches, TaskMonitor monitor)
|
private boolean applyDuplicateFunctionMatches(Collection<VTMatch> matches, TaskMonitor monitor)
|
||||||
|
@ -409,19 +450,22 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
boolean someMatchesHaveMarkupErrors = false;
|
boolean someMatchesHaveMarkupErrors = false;
|
||||||
Set<VTMatch> copyOfMatches = new HashSet<>(matches);
|
Set<VTMatch> copyOfMatches = new HashSet<>(matches);
|
||||||
|
|
||||||
// Process matches in related sets of matches
|
String message = "Processing match %d of %d...";
|
||||||
for (VTMatch match : matches) {
|
int n = matches.size();
|
||||||
|
Iterator<VTMatch> it = matches.iterator();
|
||||||
|
for (int i = 0; it.hasNext(); i++) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
|
monitor.setMessage(String.format(message, i, n));
|
||||||
|
|
||||||
// if match has already been removed (ie it was in a set that was already processed)
|
VTMatch match = it.next();
|
||||||
// then skip it
|
|
||||||
|
// skip if match has already been removed (it was in a set that was already processed)
|
||||||
if (!copyOfMatches.contains(match)) {
|
if (!copyOfMatches.contains(match)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get a set of related matches from the set of all matches
|
// Get a set of related matches from the set of all matches. These all have the same
|
||||||
// ie these all have the same instructions as each other but not necessarily
|
// instructions as each other but not necessarily the same operands.
|
||||||
// the same operands.
|
|
||||||
Set<VTMatch> relatedMatches = getRelatedMatches(match, matches, monitor);
|
Set<VTMatch> relatedMatches = getRelatedMatches(match, matches, monitor);
|
||||||
|
|
||||||
// remove related matches from the set of matches to process next time
|
// remove related matches from the set of matches to process next time
|
||||||
|
@ -440,19 +484,19 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
Set<Address> uniqueDestFunctionAddresses =
|
Set<Address> uniqueDestFunctionAddresses =
|
||||||
dedupMatchingFunctions(destinationProgram, destAddresses, monitor);
|
dedupMatchingFunctions(destinationProgram, destAddresses, monitor);
|
||||||
|
|
||||||
// Keep only matches containing the unique sources and destination functions determined above
|
// Keep only matches containing unique source and destination functions from above
|
||||||
Set<VTMatch> dedupedMatches = getMatches(relatedMatches, uniqueSourceFunctionAddresses,
|
Set<VTMatch> dedupedMatches = getMatches(relatedMatches, uniqueSourceFunctionAddresses,
|
||||||
uniqueDestFunctionAddresses, monitor);
|
uniqueDestFunctionAddresses, monitor);
|
||||||
|
|
||||||
// Loop through all the source functions
|
// loop through all the source functions
|
||||||
for (Address sourceAddress : uniqueSourceFunctionAddresses) {
|
for (Address sourceAddress : uniqueSourceFunctionAddresses) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
|
|
||||||
// Find all destination functions with equivalent operands to current source function
|
// find all destination functions with equivalent operands to source function
|
||||||
Set<VTMatch> matchesWithEquivalentOperands = getMatchesWithEquivalentOperands(
|
Set<VTMatch> matchesWithEquivalentOperands = getMatchesWithEquivalentOperands(
|
||||||
dedupedMatches, sourceAddress, uniqueDestFunctionAddresses, monitor);
|
dedupedMatches, sourceAddress, uniqueDestFunctionAddresses, monitor);
|
||||||
|
|
||||||
// If there is just one equivalent match try to accept the match and apply markup
|
// if there is just one equivalent match try to accept the match and apply markup
|
||||||
if (matchesWithEquivalentOperands.size() == 1) {
|
if (matchesWithEquivalentOperands.size() == 1) {
|
||||||
VTMatch theMatch = CollectionUtils.any(matchesWithEquivalentOperands);
|
VTMatch theMatch = CollectionUtils.any(matchesWithEquivalentOperands);
|
||||||
someMatchesHaveMarkupErrors |=
|
someMatchesHaveMarkupErrors |=
|
||||||
|
@ -814,7 +858,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
* @return Set of addresses of deduped function bytes
|
* @return Set of addresses of deduped function bytes
|
||||||
* @throws CancelledException if cancelled
|
* @throws CancelledException if cancelled
|
||||||
*/
|
*/
|
||||||
public Set<Address> dedupMatchingFunctions(Program program, Set<Address> addresses,
|
private Set<Address> dedupMatchingFunctions(Program program, Set<Address> addresses,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
|
@ -859,13 +903,54 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||||
return uniqueFunctionAddresses;
|
return uniqueFunctionAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMsg;
|
return statusMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A task monitor that allows us to control the message content and the progress */
|
||||||
|
private class SubTaskMonitor extends WrappingTaskMonitor {
|
||||||
|
|
||||||
|
private String prefix;
|
||||||
|
|
||||||
|
SubTaskMonitor(TaskMonitor delegate) {
|
||||||
|
super(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPrefix(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void doIncrementProgress() {
|
||||||
|
super.incrementProgress(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doInitialize(long max) {
|
||||||
|
super.initialize(max);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public void setMessage(String message) {
|
||||||
return "Auto Version Tracking Command";
|
super.setMessage(prefix + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(long max) {
|
||||||
|
// we control the max value
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setMaximum(long max) {
|
||||||
|
// we control the max value
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProgress(long value) {
|
||||||
|
// we control the progress
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incrementProgress(long incrementAmount) {
|
||||||
|
// we control progress
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -182,8 +182,8 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||||
int filteredCount = matchesTableModel.getRowCount();
|
int filteredCount = matchesTableModel.getRowCount();
|
||||||
int unfilteredCount = matchesTableModel.getUnfilteredRowCount();
|
int unfilteredCount = matchesTableModel.getUnfilteredRowCount();
|
||||||
int filteredOutCount = unfilteredCount - filteredCount;
|
int filteredOutCount = unfilteredCount - filteredCount;
|
||||||
ancillaryFilterButton.setToolTipText(
|
ancillaryFilterButton
|
||||||
"More Filters - " + filteredOutCount + " item(s) hidden");
|
.setToolTipText("More Filters - " + filteredOutCount + " item(s) hidden");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ancillaryFilterButton.setToolTipText("More Filters - no active filters");
|
ancillaryFilterButton.setToolTipText("More Filters - no active filters");
|
||||||
|
@ -233,9 +233,9 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||||
int unfilteredCount = matchesTableModel.getUnfilteredRowCount();
|
int unfilteredCount = matchesTableModel.getUnfilteredRowCount();
|
||||||
|
|
||||||
String sessionName = controller.getVersionTrackingSessionName();
|
String sessionName = controller.getVersionTrackingSessionName();
|
||||||
StringBuffer buffy = new StringBuffer();
|
StringBuilder buffy = new StringBuilder();
|
||||||
buffy.append("[Session: ").append(sessionName).append("] ");
|
buffy.append("[Session: ").append(sessionName).append("] - ");
|
||||||
buffy.append('-').append(filteredCount).append(" matches");
|
buffy.append(filteredCount).append(" matches");
|
||||||
if (filteredCount != unfilteredCount) {
|
if (filteredCount != unfilteredCount) {
|
||||||
buffy.append(" (of ").append(unfilteredCount).append(')');
|
buffy.append(" (of ").append(unfilteredCount).append(')');
|
||||||
}
|
}
|
||||||
|
@ -307,14 +307,14 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||||
|
|
||||||
int sourceLabelColumnIndex = matchesTableModel.getColumnIndex(SourceLabelTableColumn.class);
|
int sourceLabelColumnIndex = matchesTableModel.getColumnIndex(SourceLabelTableColumn.class);
|
||||||
TableColumn sourceLabelColumn = columnModel.getColumn(sourceLabelColumnIndex);
|
TableColumn sourceLabelColumn = columnModel.getColumn(sourceLabelColumnIndex);
|
||||||
sourceLabelColumn.setCellRenderer(
|
sourceLabelColumn
|
||||||
new VTSymbolRenderer(controller.getServiceProvider(), table));
|
.setCellRenderer(new VTSymbolRenderer(controller.getServiceProvider(), table));
|
||||||
|
|
||||||
int destinationLabelColumnIndex =
|
int destinationLabelColumnIndex =
|
||||||
matchesTableModel.getColumnIndex(DestinationLabelTableColumn.class);
|
matchesTableModel.getColumnIndex(DestinationLabelTableColumn.class);
|
||||||
TableColumn destinationLabelColumn = columnModel.getColumn(destinationLabelColumnIndex);
|
TableColumn destinationLabelColumn = columnModel.getColumn(destinationLabelColumnIndex);
|
||||||
destinationLabelColumn.setCellRenderer(
|
destinationLabelColumn
|
||||||
new VTSymbolRenderer(controller.getServiceProvider(), table));
|
.setCellRenderer(new VTSymbolRenderer(controller.getServiceProvider(), table));
|
||||||
|
|
||||||
int statusColumnIndex = matchesTableModel.getColumnIndex(StatusTableColumn.class);
|
int statusColumnIndex = matchesTableModel.getColumnIndex(StatusTableColumn.class);
|
||||||
TableColumn statusColumn = columnModel.getColumn(statusColumnIndex);
|
TableColumn statusColumn = columnModel.getColumn(statusColumnIndex);
|
||||||
|
@ -352,8 +352,8 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||||
innerPanel.add(lengthFilterPanel);
|
innerPanel.add(lengthFilterPanel);
|
||||||
|
|
||||||
ancillaryFilterButton = new JButton(UNFILTERED_ICON);
|
ancillaryFilterButton = new JButton(UNFILTERED_ICON);
|
||||||
ancillaryFilterButton.addActionListener(
|
ancillaryFilterButton
|
||||||
e -> tool.showDialog(ancillaryFilterDialog, component));
|
.addActionListener(e -> tool.showDialog(ancillaryFilterDialog, component));
|
||||||
ancillaryFilterButton.setToolTipText("Filters Dialog");
|
ancillaryFilterButton.setToolTipText("Filters Dialog");
|
||||||
HelpService helpService = DockingWindowManager.getHelpService();
|
HelpService helpService = DockingWindowManager.getHelpService();
|
||||||
HelpLocation filterHelpLocation =
|
HelpLocation filterHelpLocation =
|
||||||
|
@ -695,8 +695,7 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||||
"should become ignored by applying a match.");
|
"should become ignored by applying a match.");
|
||||||
|
|
||||||
vtOptions.getOptions(APPLY_MARKUP_OPTIONS_NAME)
|
vtOptions.getOptions(APPLY_MARKUP_OPTIONS_NAME)
|
||||||
.registerOptionsEditor(
|
.registerOptionsEditor(new ApplyMarkupPropertyEditor(controller));
|
||||||
new ApplyMarkupPropertyEditor(controller));
|
|
||||||
vtOptions.getOptions(DISPLAY_APPLY_MARKUP_OPTIONS)
|
vtOptions.getOptions(DISPLAY_APPLY_MARKUP_OPTIONS)
|
||||||
.setOptionsHelpLocation(
|
.setOptionsHelpLocation(
|
||||||
new HelpLocation("VersionTracking", "Apply Markup Options"));
|
new HelpLocation("VersionTracking", "Apply Markup Options"));
|
||||||
|
@ -709,12 +708,10 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||||
vtOptions.setOptionsHelpLocation(applyOptionsHelpLocation);
|
vtOptions.setOptionsHelpLocation(applyOptionsHelpLocation);
|
||||||
|
|
||||||
vtOptions.getOptions(ACCEPT_MATCH_OPTIONS_NAME)
|
vtOptions.getOptions(ACCEPT_MATCH_OPTIONS_NAME)
|
||||||
.setOptionsHelpLocation(
|
.setOptionsHelpLocation(applyMatchOptionsHelpLocation);
|
||||||
applyMatchOptionsHelpLocation);
|
|
||||||
|
|
||||||
vtOptions.getOptions(APPLY_MARKUP_OPTIONS_NAME)
|
vtOptions.getOptions(APPLY_MARKUP_OPTIONS_NAME)
|
||||||
.setOptionsHelpLocation(
|
.setOptionsHelpLocation(applyMatchOptionsHelpLocation);
|
||||||
applyMatchOptionsHelpLocation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
|
@ -41,11 +41,8 @@ public abstract class VtTask extends Task {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void run(TaskMonitor monitor) {
|
public final void run(TaskMonitor monitor) {
|
||||||
boolean restoreEvents = false;
|
boolean restoreEvents = suspendEvents();
|
||||||
if (session != null && shouldSuspendSessionEvents()) {
|
|
||||||
session.setEventsEnabled(false);
|
|
||||||
restoreEvents = true;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
success = doWork(monitor);
|
success = doWork(monitor);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +59,24 @@ public abstract class VtTask extends Task {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean suspendEvents() {
|
||||||
|
|
||||||
|
if (session == null) {
|
||||||
|
return false; // no events to suspend
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shouldSuspendSessionEvents()) {
|
||||||
|
return false; // this task has chosen not to suspend events
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!session.isSendingEvents()) {
|
||||||
|
return false; // someone external to this task is managing events
|
||||||
|
}
|
||||||
|
|
||||||
|
session.setEventsEnabled(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if session events should be suspended during task execution.
|
* Determine if session events should be suspended during task execution.
|
||||||
* This can improve performance during task execution at the expense of bulk
|
* This can improve performance during task execution at the expense of bulk
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static ghidra.feature.vt.db.VTTestUtils.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ import ghidra.feature.vt.api.main.*;
|
||||||
import ghidra.feature.vt.api.util.VTAssociationStatusException;
|
import ghidra.feature.vt.api.util.VTAssociationStatusException;
|
||||||
import ghidra.feature.vt.db.VTTestUtils;
|
import ghidra.feature.vt.db.VTTestUtils;
|
||||||
import ghidra.feature.vt.gui.VTTestEnv;
|
import ghidra.feature.vt.gui.VTTestEnv;
|
||||||
import ghidra.feature.vt.gui.actions.AutoVersionTrackingCommand;
|
import ghidra.feature.vt.gui.actions.AutoVersionTrackingTask;
|
||||||
import ghidra.feature.vt.gui.plugin.VTController;
|
import ghidra.feature.vt.gui.plugin.VTController;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
|
@ -42,7 +41,7 @@ import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskLauncher;
|
||||||
|
|
||||||
public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTest {
|
public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
|
@ -84,8 +83,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
controller = env.getVTController();
|
controller = env.getVTController();
|
||||||
|
|
||||||
// Score .999999 and confidence 10.0 (log10 confidence 2.0) and up
|
// Score .999999 and confidence 10.0 (log10 confidence 2.0) and up
|
||||||
boolean success = runAutoVTCommand(0.999999999, 10.0);
|
runAutoVTCommand(0.999999999, 10.0);
|
||||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
|
||||||
|
|
||||||
// verify that the default options are what we expect
|
// verify that the default options are what we expect
|
||||||
// if this assert fails then the follow-on tests will probably fail
|
// if this assert fails then the follow-on tests will probably fail
|
||||||
|
@ -146,8 +144,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
|
|
||||||
// Score 0.5 and conf threshold 1.0 allow similarity scores of higher than 0.5 for combined
|
// Score 0.5 and conf threshold 1.0 allow similarity scores of higher than 0.5 for combined
|
||||||
// reference correlator and 1.0 and higher for the log 10 confidence score
|
// reference correlator and 1.0 and higher for the log 10 confidence score
|
||||||
boolean success = runAutoVTCommand(0.5, 1.0);
|
runAutoVTCommand(0.5, 1.0);
|
||||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
|
||||||
|
|
||||||
// verify that the default options are what we expect
|
// verify that the default options are what we expect
|
||||||
// if this assert fails then the follow-on tests will probably fail
|
// if this assert fails then the follow-on tests will probably fail
|
||||||
|
@ -613,8 +610,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
sourceProgram.endTransaction(startTransaction, true);
|
sourceProgram.endTransaction(startTransaction, true);
|
||||||
|
|
||||||
// run Auto VT
|
// run Auto VT
|
||||||
boolean success = runAutoVTCommand(1.0, 10.0);
|
runAutoVTCommand(1.0, 10.0);
|
||||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
|
||||||
|
|
||||||
// Check that the match we are interested in got accepted
|
// Check that the match we are interested in got accepted
|
||||||
String correlator = "Combined Function and Data Reference Match";
|
String correlator = "Combined Function and Data Reference Match";
|
||||||
|
@ -670,8 +666,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
sourceProgram.endTransaction(startTransaction, true);
|
sourceProgram.endTransaction(startTransaction, true);
|
||||||
|
|
||||||
// run Auto VT
|
// run Auto VT
|
||||||
boolean success = runAutoVTCommand(1.0, 10.0);
|
runAutoVTCommand(1.0, 10.0);
|
||||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
|
||||||
|
|
||||||
// Check that the match we are interested in got accepted
|
// Check that the match we are interested in got accepted
|
||||||
String correlator = "Duplicate Function Instructions Match";
|
String correlator = "Duplicate Function Instructions Match";
|
||||||
|
@ -735,8 +730,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
|
|
||||||
// Now run the AutoVT command with lower confidence thresholds to allow the match we want to
|
// Now run the AutoVT command with lower confidence thresholds to allow the match we want to
|
||||||
// test in as a match
|
// test in as a match
|
||||||
boolean success = runAutoVTCommand(0.5, 1.0);
|
runAutoVTCommand(0.5, 1.0);
|
||||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
|
||||||
|
|
||||||
// Check that the match we are interested in got accepted
|
// Check that the match we are interested in got accepted
|
||||||
String correlator = "Combined Function and Data Reference Match";
|
String correlator = "Combined Function and Data Reference Match";
|
||||||
|
@ -829,20 +823,18 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
assertEquals(expectedAcceptedMatchCount, getNumAcceptedMatches(vtSession, correlatorName));
|
assertEquals(expectedAcceptedMatchCount, getNumAcceptedMatches(vtSession, correlatorName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean runAutoVTCommand(double minReferenceCorrelatorScore,
|
private void runAutoVTCommand(double minReferenceCorrelatorScore,
|
||||||
double minReferenceCorrelatorConfidence) {
|
double minReferenceCorrelatorConfidence) {
|
||||||
AtomicBoolean result = new AtomicBoolean();
|
|
||||||
runSwing(() -> {
|
|
||||||
String transactionName = "Auto Version Tracking Test";
|
|
||||||
int startTransaction = session.startTransaction(transactionName);
|
|
||||||
|
|
||||||
AutoVersionTrackingCommand vtCommand = new AutoVersionTrackingCommand(controller,
|
AutoVersionTrackingTask task = new AutoVersionTrackingTask(controller, session,
|
||||||
session, minReferenceCorrelatorScore, minReferenceCorrelatorConfidence);
|
minReferenceCorrelatorScore, minReferenceCorrelatorConfidence);
|
||||||
result.set(vtCommand.applyTo(session, TaskMonitor.DUMMY));
|
TaskLauncher.launch(task);
|
||||||
|
waitForSession();
|
||||||
|
}
|
||||||
|
|
||||||
session.endTransaction(startTransaction, result.get());
|
private void waitForSession() {
|
||||||
});
|
session.flushEvents();
|
||||||
return result.get();
|
waitForSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private VTMatchSet getVTMatchSet(VTSession vtSession, String correlatorName) {
|
private VTMatchSet getVTMatchSet(VTSession vtSession, String correlatorName) {
|
||||||
|
|
|
@ -74,6 +74,7 @@ public interface DomainObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the object has changed.
|
* Returns whether the object has changed.
|
||||||
|
* @return whether the object has changed.
|
||||||
*/
|
*/
|
||||||
public boolean isChanged();
|
public boolean isChanged();
|
||||||
|
|
||||||
|
@ -87,17 +88,19 @@ public interface DomainObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this object has been marked as Temporary.
|
* Returns true if this object has been marked as Temporary.
|
||||||
|
* @return true if this object has been marked as Temporary.
|
||||||
*/
|
*/
|
||||||
public boolean isTemporary();
|
public boolean isTemporary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if changes are permitted.
|
* Returns true if changes are permitted.
|
||||||
|
* @return true if changes are permitted.
|
||||||
*/
|
*/
|
||||||
public boolean isChangeable();
|
public boolean isChangeable();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this object can be saved; a read-only file
|
* Returns true if this object can be saved; a read-only file cannot be saved.
|
||||||
* cannot be saved.
|
* @return true if this object can be saved
|
||||||
*/
|
*/
|
||||||
public boolean canSave();
|
public boolean canSave();
|
||||||
|
|
||||||
|
@ -118,8 +121,8 @@ public interface DomainObject {
|
||||||
* Saves (i.e., serializes) the current content to a packed file.
|
* Saves (i.e., serializes) the current content to a packed file.
|
||||||
* @param outputFile packed output file
|
* @param outputFile packed output file
|
||||||
* @param monitor progress monitor
|
* @param monitor progress monitor
|
||||||
* @throws IOException
|
* @throws IOException if an exception occurs
|
||||||
* @throws CancelledException
|
* @throws CancelledException if the user cancels
|
||||||
* @throws UnsupportedOperationException if not supported by object implementation
|
* @throws UnsupportedOperationException if not supported by object implementation
|
||||||
*/
|
*/
|
||||||
public void saveToPackedFile(File outputFile, TaskMonitor monitor)
|
public void saveToPackedFile(File outputFile, TaskMonitor monitor)
|
||||||
|
@ -179,11 +182,13 @@ public interface DomainObject {
|
||||||
/**
|
/**
|
||||||
* Returns a word or short phrase that best describes or categorizes
|
* Returns a word or short phrase that best describes or categorizes
|
||||||
* the object in terms that a user will understand.
|
* the object in terms that a user will understand.
|
||||||
|
* @return the description
|
||||||
*/
|
*/
|
||||||
public String getDescription();
|
public String getDescription();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of this domain object.
|
* Get the name of this domain object.
|
||||||
|
* @return the name
|
||||||
*/
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
|
@ -239,6 +244,7 @@ public interface DomainObject {
|
||||||
* Returns true if this object is sending out events as it is changed. The default is
|
* Returns true if this object is sending out events as it is changed. The default is
|
||||||
* true. You can change this value by calling {@link #setEventsEnabled(boolean)}.
|
* true. You can change this value by calling {@link #setEventsEnabled(boolean)}.
|
||||||
*
|
*
|
||||||
|
* @return true if sending events
|
||||||
* @see #setEventsEnabled(boolean)
|
* @see #setEventsEnabled(boolean)
|
||||||
*/
|
*/
|
||||||
public boolean isSendingEvents();
|
public boolean isSendingEvents();
|
||||||
|
@ -258,26 +264,27 @@ public interface DomainObject {
|
||||||
* Returns true if a modification lock can be obtained on this
|
* Returns true if a modification lock can be obtained on this
|
||||||
* domain object. Care should be taken with using this method since
|
* domain object. Care should be taken with using this method since
|
||||||
* this will not prevent another thread from modifying the domain object.
|
* this will not prevent another thread from modifying the domain object.
|
||||||
|
* @return true if can lock
|
||||||
*/
|
*/
|
||||||
public boolean canLock();
|
public boolean canLock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the domain object currenly has a modification lock enabled.
|
* Returns true if the domain object currently has a modification lock enabled.
|
||||||
|
* @return true if locked
|
||||||
*/
|
*/
|
||||||
public boolean isLocked();
|
public boolean isLocked();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to obtain a modification lock on the domain object. Multiple locks
|
* Attempt to obtain a modification lock on the domain object. Multiple locks may be granted
|
||||||
* may be granted on this domain object, although all lock owners must release their
|
* on this domain object, although all lock owners must release their lock in a timely fashion.
|
||||||
* lock in a timely fashion.
|
|
||||||
* @param reason very short reason for requesting lock
|
* @param reason very short reason for requesting lock
|
||||||
* @return true if lock obtained successfully, else false which indicates that a
|
* @return true if lock obtained successfully, else false which indicates that a modification
|
||||||
* modification is in process.
|
* is in process.
|
||||||
*/
|
*/
|
||||||
public boolean lock(String reason);
|
public boolean lock(String reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels any previous lock and aquires it.
|
* Cancels any previous lock and acquires it.
|
||||||
* @param rollback if true, any changes in made with the previous lock should be discarded.
|
* @param rollback if true, any changes in made with the previous lock should be discarded.
|
||||||
* @param reason very short reason for requesting lock
|
* @param reason very short reason for requesting lock
|
||||||
*/
|
*/
|
||||||
|
@ -298,17 +305,20 @@ public interface DomainObject {
|
||||||
/**
|
/**
|
||||||
* Get the property list for the given name.
|
* Get the property list for the given name.
|
||||||
* @param propertyListName name of property list
|
* @param propertyListName name of property list
|
||||||
|
* @return the options
|
||||||
*/
|
*/
|
||||||
public Options getOptions(String propertyListName);
|
public Options getOptions(String propertyListName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this domain object has been closed as a result of the last release
|
* Returns true if this domain object has been closed as a result of the last release
|
||||||
|
* @return true if closed
|
||||||
*/
|
*/
|
||||||
public boolean isClosed();
|
public boolean isClosed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the user has exclusive access to the domain object. Exclusive access means
|
* Returns true if the user has exclusive access to the domain object. Exclusive access means
|
||||||
* either the object is not shared or the user has an exclusive checkout on the object.
|
* either the object is not shared or the user has an exclusive checkout on the object.
|
||||||
|
* @return true if has exclusive access
|
||||||
*/
|
*/
|
||||||
public boolean hasExclusiveAccess();
|
public boolean hasExclusiveAccess();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue