mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-12-06 19:11:37 +00:00
GP-1421 - Version Tracking - Updated API code to use the current in-use
task monitor to allow for the cancelling of slow implied match finding. Closes #3221
This commit is contained in:
parent
53e4f2ff9b
commit
e55550edfd
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.memory;
|
||||
|
||||
import static ghidra.lifecycle.Unfinished.TODO;
|
||||
import static ghidra.lifecycle.Unfinished.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
@ -28,6 +28,7 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.*;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
@ -35,6 +36,7 @@ import docking.action.DockingActionIf;
|
||||
import docking.menu.ActionState;
|
||||
import docking.menu.MultiStateDockingAction;
|
||||
import docking.widgets.EventTrigger;
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.plugin.core.byteviewer.ByteViewerComponent;
|
||||
import ghidra.app.plugin.core.byteviewer.ByteViewerPanel;
|
||||
@ -62,6 +64,7 @@ import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
static LocationTrackingSpec getLocationTrackingSpec(String name) {
|
||||
return LocationTrackingSpec.fromConfigName(name);
|
||||
@ -78,8 +81,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
final LocationTrackingSpec trackSp =
|
||||
getLocationTrackingSpec(SPLocationTrackingSpec.CONFIG_NAME);
|
||||
|
||||
final AutoReadMemorySpec readNone =
|
||||
getAutoReadMemorySpec(NoneAutoReadMemorySpec.CONFIG_NAME);
|
||||
final AutoReadMemorySpec readNone = getAutoReadMemorySpec(NoneAutoReadMemorySpec.CONFIG_NAME);
|
||||
final AutoReadMemorySpec readVisible =
|
||||
getAutoReadMemorySpec(VisibleAutoReadMemorySpec.CONFIG_NAME);
|
||||
final AutoReadMemorySpec readVisROOnce =
|
||||
@ -254,8 +256,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
createAndOpenTrace();
|
||||
TraceThread thread1;
|
||||
TraceThread thread2;
|
||||
DebuggerMemoryBytesProvider extraProvider = SwingExecutorService.INSTANCE.submit(
|
||||
() -> memBytesPlugin.createViewerIfMissing(trackPc, true)).get();
|
||||
DebuggerMemoryBytesProvider extraProvider = SwingExecutorService.INSTANCE
|
||||
.submit(() -> memBytesPlugin.createViewerIfMissing(trackPc, true))
|
||||
.get();
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
@ -322,8 +325,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking()
|
||||
throws Exception {
|
||||
public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking() throws Exception {
|
||||
memBytesProvider.setTrackingSpec(trackNone);
|
||||
try ( //
|
||||
ToyDBTraceBuilder b1 =
|
||||
@ -374,8 +376,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking()
|
||||
throws Exception {
|
||||
public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking() throws Exception {
|
||||
memBytesProvider.setTrackingSpec(trackNone);
|
||||
try ( //
|
||||
ToyDBTraceBuilder b1 =
|
||||
@ -426,8 +427,8 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertViewerBackgroundAt(Color expected, ByteViewerPanel panel,
|
||||
Address addr) throws AWTException, InterruptedException {
|
||||
protected void assertViewerBackgroundAt(Color expected, ByteViewerPanel panel, Address addr)
|
||||
throws AWTException, InterruptedException {
|
||||
goToDyn(addr);
|
||||
waitForPass(() -> {
|
||||
Rectangle r = panel.getBounds();
|
||||
@ -577,8 +578,8 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
assertEquals(traceManager.getCurrentView(), memBytesProvider.getProgram());
|
||||
assertEquals("(nowhere)", memBytesProvider.locationLabel.getText());
|
||||
|
||||
DebuggerMemoryBytesProvider extraProvider = runSwing(
|
||||
() -> memBytesPlugin.createViewerIfMissing(trackNone, false));
|
||||
DebuggerMemoryBytesProvider extraProvider =
|
||||
runSwing(() -> memBytesPlugin.createViewerIfMissing(trackNone, false));
|
||||
waitForSwing();
|
||||
assertEquals(traceManager.getCurrentView(), extraProvider.getProgram());
|
||||
assertEquals("(nowhere)", extraProvider.locationLabel.getText());
|
||||
@ -716,8 +717,8 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
traceManager.activateThread(thread1);
|
||||
|
||||
// NOTE: Action does not exist for main dynamic listing
|
||||
DebuggerMemoryBytesProvider extraProvider = runSwing(
|
||||
() -> memBytesPlugin.createViewerIfMissing(trackNone, true));
|
||||
DebuggerMemoryBytesProvider extraProvider =
|
||||
runSwing(() -> memBytesPlugin.createViewerIfMissing(trackNone, true));
|
||||
waitForSwing();
|
||||
assertTrue(extraProvider.actionFollowsCurrentThread.isEnabled());
|
||||
assertTrue(extraProvider.actionFollowsCurrentThread.isSelected());
|
||||
@ -844,8 +845,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
assertEquals(readVisROOnce, memBytesProvider.getAutoReadMemorySpec());
|
||||
assertEquals(readVisROOnce, memBytesProvider.actionAutoReadMemory.getCurrentUserData());
|
||||
|
||||
memBytesProvider.actionAutoReadMemory
|
||||
.setCurrentActionStateByUserData(readNone);
|
||||
memBytesProvider.actionAutoReadMemory.setCurrentActionStateByUserData(readNone);
|
||||
waitForSwing();
|
||||
assertEquals(readNone, memBytesProvider.getAutoReadMemorySpec());
|
||||
assertEquals(readNone, memBytesProvider.actionAutoReadMemory.getCurrentUserData());
|
||||
@ -886,8 +886,8 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
TraceModule modExe;
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
modExe = tb.trace.getModuleManager()
|
||||
.addModule("modExe", "modExe",
|
||||
tb.range(0x55550000, 0x555501ff), Range.atLeast(0L));
|
||||
.addModule("modExe", "modExe", tb.range(0x55550000, 0x555501ff),
|
||||
Range.atLeast(0L));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
waitForPass(() -> assertEquals("modExe", memBytesProvider.locationLabel.getText()));
|
||||
|
@ -27,8 +27,10 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import generic.Unique;
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.app.plugin.core.debug.event.ModelObjectFocusedPluginEvent;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractConnectAction;
|
||||
@ -53,10 +55,11 @@ import mockit.VerificationsInOrder;
|
||||
|
||||
/**
|
||||
* TODO: Cover the error cases, and cases where {@code null} is expected
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* TODO: Cover cases where multiple recorders are present
|
||||
*/
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITest
|
||||
implements DebuggerModelTestUtils {
|
||||
protected static final long TIMEOUT_MILLIS =
|
||||
@ -67,7 +70,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
* CollectionChangeListener.of() if I try to mock one of those or a subclass directly. I'm
|
||||
* guessing the version we're using (1.44 as of this writing) is utterly ignorant of static
|
||||
* interface methods. What was the latest version of Java at the time?
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* TODO: Check if a later version fixes this issue. If so, consider upgrading. If not, submit an
|
||||
* issue.
|
||||
@ -582,8 +585,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
public void testRecordBestOfferUnrecognized() throws Exception {
|
||||
createTestModel();
|
||||
mb.testModel.session.environment.changeAttributes(List.of(),
|
||||
Map.of(TargetEnvironment.ARCH_ATTRIBUTE_NAME, "test-bogus-arch"),
|
||||
"Testing");
|
||||
Map.of(TargetEnvironment.ARCH_ATTRIBUTE_NAME, "test-bogus-arch"), "Testing");
|
||||
mb.createTestProcessesAndThreads();
|
||||
|
||||
modelService.recordTargetBestOffer(mb.testProcess1);
|
||||
@ -609,8 +611,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
public void testRecordPromptOffersUnrecognized() throws Exception {
|
||||
createTestModel();
|
||||
mb.testModel.session.environment.changeAttributes(List.of(),
|
||||
Map.of(TargetEnvironment.ARCH_ATTRIBUTE_NAME, "test-bogus-arch"),
|
||||
"Testing");
|
||||
Map.of(TargetEnvironment.ARCH_ATTRIBUTE_NAME, "test-bogus-arch"), "Testing");
|
||||
mb.createTestProcessesAndThreads();
|
||||
|
||||
runSwingLater(() -> modelService.recordTargetPromptOffers(mb.testProcess1));
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,13 +15,13 @@
|
||||
*/
|
||||
package ghidra.util.table;
|
||||
|
||||
import docking.widgets.table.threaded.ThreadedTableModel;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import docking.widgets.table.threaded.ThreadedTableModel;
|
||||
|
||||
public abstract class GhidraProgramTableModel<ROW_TYPE> extends
|
||||
ThreadedTableModel<ROW_TYPE, Program> implements ProgramTableModel {
|
||||
public abstract class GhidraProgramTableModel<ROW_TYPE>
|
||||
extends ThreadedTableModel<ROW_TYPE, Program> implements ProgramTableModel {
|
||||
|
||||
protected Program program;
|
||||
|
||||
@ -47,9 +46,10 @@ public abstract class GhidraProgramTableModel<ROW_TYPE> extends
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point for getting a row-specific program. Most models don't need this
|
||||
* capability.
|
||||
* Extension point for getting a row-specific program. Most models don't need this
|
||||
* capability.
|
||||
* @param t The ROW_TYPE row object
|
||||
* @return the program
|
||||
*/
|
||||
protected Program getProgramForRow(ROW_TYPE t) {
|
||||
return getProgram();
|
||||
|
@ -32,3 +32,9 @@ dependencies {
|
||||
testImplementation "org.jmockit:jmockit:1.44"
|
||||
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
||||
}
|
||||
integrationTest {
|
||||
// tests to slow to run during automated testing
|
||||
excludes = [
|
||||
'**/VTAutoVersionTrackingTest*',
|
||||
]
|
||||
}
|
||||
|
@ -29,12 +29,20 @@ import ghidra.program.database.DBObjectCache;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.Lock;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
private VTAssociationTableDBAdapter associationTableAdapter;
|
||||
|
||||
private final VTSessionDB session;
|
||||
|
||||
private VTAssociationTableDBAdapter associationTableAdapter;
|
||||
|
||||
// A cache of accepted associations that allow this class to check isBlocked() quickly. This
|
||||
// was added to fix a major performance bottleneck.
|
||||
private Set<Address> acceptedSourceAssociations = new HashSet<>();
|
||||
private Set<Address> acceptedDestinationAssociations = new HashSet<>();
|
||||
|
||||
private VTMatchMarkupItemTableDBAdapter markupItemTableAdapter;
|
||||
private DBObjectCache<MarkupItemStorageDB> markupItemCache;
|
||||
private List<AssociationHook> associationHooks = new ArrayList<>();
|
||||
@ -56,6 +64,7 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
VTAssociationTableDBAdapter.getAdapter(dbHandle, openMode, monitor);
|
||||
manager.markupItemTableAdapter =
|
||||
VTMatchMarkupItemTableDBAdapter.getAdapter(dbHandle, openMode, monitor);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
@ -66,6 +75,39 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
markupItemCache = new DBObjectCache<>(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an existing session has been initialized with its programs. This is not called
|
||||
* when a new session is created.
|
||||
*/
|
||||
void sessionInitialized() {
|
||||
TaskLauncher.launchModal("Loading Associations",
|
||||
monitor -> loadAcceptedAssociations(monitor));
|
||||
}
|
||||
|
||||
private void loadAcceptedAssociations(TaskMonitor monitor) {
|
||||
|
||||
monitor.setMessage("Loading accepted associations...");
|
||||
|
||||
try {
|
||||
RecordIterator it = associationTableAdapter.getRecords();
|
||||
while (it.hasNext() && !monitor.isCancelled()) {
|
||||
DBRecord record = it.next();
|
||||
VTAssociationDB associationDB = getAssociationForRecord(record);
|
||||
VTAssociationStatus status = associationDB.getStatus();
|
||||
if (status == ACCEPTED) {
|
||||
Address sourceAddress = associationDB.getSourceAddress();
|
||||
Address destinationAddress = associationDB.getDestinationAddress();
|
||||
acceptedSourceAssociations.add(sourceAddress);
|
||||
acceptedDestinationAssociations.add(destinationAddress);
|
||||
}
|
||||
}
|
||||
monitor.setMessage("Finished loading accepted associations");
|
||||
}
|
||||
catch (IOException e) {
|
||||
session.dbError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MarkupItemStorageDB> getAppliedMarkupItems(TaskMonitor monitor,
|
||||
VTAssociation association) throws CancelledException {
|
||||
|
||||
@ -222,8 +264,8 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
VTAssociationDB newAssociation = null;
|
||||
try {
|
||||
lock.acquire();
|
||||
DBRecord record = associationTableAdapter.insertRecord(sourceLong, destinationLong, type,
|
||||
isBlocked ? BLOCKED : AVAILABLE, 0);
|
||||
DBRecord record = associationTableAdapter.insertRecord(sourceLong, destinationLong,
|
||||
type, isBlocked ? BLOCKED : AVAILABLE, 0);
|
||||
newAssociation = new VTAssociationDB(this, associationCache, record);
|
||||
}
|
||||
catch (IOException e) {
|
||||
@ -257,22 +299,13 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
}
|
||||
|
||||
private boolean isBlocked(Address sourceAddress, Address destinationAddress) {
|
||||
long sourceID = session.getLongFromSourceAddress(sourceAddress);
|
||||
long destinationID = session.getLongFromDestinationAddress(destinationAddress);
|
||||
try {
|
||||
Set<DBRecord> relatedRecords =
|
||||
associationTableAdapter.getRelatedAssociationRecordsBySourceAndDestinationAddress(
|
||||
sourceID, destinationID);
|
||||
for (DBRecord record : relatedRecords) {
|
||||
VTAssociationDB associationDB = getAssociationForRecord(record);
|
||||
VTAssociationStatus status = associationDB.getStatus();
|
||||
if (status == ACCEPTED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptedSourceAssociations.contains(sourceAddress)) {
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
session.dbError(e);
|
||||
|
||||
if (acceptedDestinationAssociations.contains(destinationAddress)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -396,9 +429,9 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
public Collection<VTAssociation> getRelatedAssociationsBySourceAddress(Address sourceAddress) {
|
||||
lock.acquire();
|
||||
try {
|
||||
long sourceID = session.getLongFromSourceAddress(sourceAddress);
|
||||
long sourceId = session.getLongFromSourceAddress(sourceAddress);
|
||||
Set<DBRecord> relatedRecords =
|
||||
associationTableAdapter.getRelatedAssociationRecordsBySourceAddress(sourceID);
|
||||
associationTableAdapter.getRelatedAssociationRecordsBySourceAddress(sourceId);
|
||||
List<VTAssociation> associations = new ArrayList<>();
|
||||
for (DBRecord record : relatedRecords) {
|
||||
associations.add(getAssociationForRecord(record));
|
||||
@ -419,10 +452,9 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
Address destinationAddress) {
|
||||
lock.acquire();
|
||||
try {
|
||||
long destinationID = session.getLongFromDestinationAddress(destinationAddress);
|
||||
Set<DBRecord> relatedRecords =
|
||||
associationTableAdapter.getRelatedAssociationRecordsByDestinationAddress(
|
||||
destinationID);
|
||||
long destinationId = session.getLongFromDestinationAddress(destinationAddress);
|
||||
Set<DBRecord> relatedRecords = associationTableAdapter
|
||||
.getRelatedAssociationRecordsByDestinationAddress(destinationId);
|
||||
List<VTAssociation> associations = new ArrayList<>();
|
||||
for (DBRecord record : relatedRecords) {
|
||||
associations.add(getAssociationForRecord(record));
|
||||
@ -443,11 +475,11 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
Address sourceAddress, Address destinationAddress) {
|
||||
lock.acquire();
|
||||
try {
|
||||
long sourceID = session.getLongFromSourceAddress(sourceAddress);
|
||||
long destinationID = session.getLongFromDestinationAddress(destinationAddress);
|
||||
long sourceId = session.getLongFromSourceAddress(sourceAddress);
|
||||
long destinationId = session.getLongFromDestinationAddress(destinationAddress);
|
||||
Set<DBRecord> relatedRecords =
|
||||
associationTableAdapter.getRelatedAssociationRecordsBySourceAndDestinationAddress(
|
||||
sourceID, destinationID);
|
||||
sourceId, destinationId);
|
||||
List<VTAssociation> associations = new ArrayList<>();
|
||||
for (DBRecord record : relatedRecords) {
|
||||
associations.add(getAssociationForRecord(record));
|
||||
@ -566,15 +598,15 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
}
|
||||
|
||||
private Set<VTAssociationDB> getRelatedAssociations(VTAssociationDB association) {
|
||||
long sourceID = session.getLongFromSourceAddress(association.getSourceAddress());
|
||||
long destinationID =
|
||||
long sourceId = session.getLongFromSourceAddress(association.getSourceAddress());
|
||||
long destinationId =
|
||||
session.getLongFromDestinationAddress(association.getDestinationAddress());
|
||||
|
||||
Set<VTAssociationDB> relatedAssociaitons = new HashSet<>();
|
||||
try {
|
||||
Set<DBRecord> relatedRecords =
|
||||
associationTableAdapter.getRelatedAssociationRecordsBySourceAndDestinationAddress(
|
||||
sourceID, destinationID);
|
||||
sourceId, destinationId);
|
||||
relatedRecords.remove(association.getRecord()); // don't change the given association
|
||||
for (DBRecord record : relatedRecords) {
|
||||
relatedAssociaitons.add(getAssociationForRecord(record));
|
||||
@ -593,6 +625,19 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
catch (IOException e) {
|
||||
session.dbError(e);
|
||||
}
|
||||
|
||||
VTAssociationDB association = getAssociationForRecord(record);
|
||||
Address sourceAddress = association.getSourceAddress();
|
||||
Address destinationAddress = association.getDestinationAddress();
|
||||
VTAssociationStatus status = association.getStatus();
|
||||
if (status == ACCEPTED) {
|
||||
acceptedSourceAssociations.add(sourceAddress);
|
||||
acceptedDestinationAssociations.add(destinationAddress);
|
||||
}
|
||||
else {
|
||||
acceptedSourceAssociations.remove(sourceAddress);
|
||||
acceptedDestinationAssociations.remove(destinationAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void updateMarkupRecord(DBRecord record) {
|
||||
@ -632,4 +677,8 @@ public class AssociationDatabaseManager implements VTAssociationManager {
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
acceptedSourceAssociations.clear();
|
||||
acceptedDestinationAssociations.clear();
|
||||
}
|
||||
}
|
||||
|
@ -61,10 +61,9 @@ public abstract class VTAssociationTableDBAdapter {
|
||||
|
||||
abstract void deleteRecord(long sourceAddressID) throws IOException;
|
||||
|
||||
abstract RecordIterator getRecordsForSourceAddress(long sourceAddressID) throws IOException;
|
||||
abstract RecordIterator getRecordsForSourceAddress(long addressID) throws IOException;
|
||||
|
||||
abstract RecordIterator getRecordsForDestinationAddress(long destinationAddressID)
|
||||
throws IOException;
|
||||
abstract RecordIterator getRecordsForDestinationAddress(long addressID) throws IOException;
|
||||
|
||||
abstract int getRecordCount();
|
||||
|
||||
@ -78,8 +77,8 @@ public abstract class VTAssociationTableDBAdapter {
|
||||
abstract Set<DBRecord> getRelatedAssociationRecordsBySourceAddress(long sourceAddressID)
|
||||
throws IOException;
|
||||
|
||||
abstract Set<DBRecord> getRelatedAssociationRecordsByDestinationAddress(long destinationAddressID)
|
||||
throws IOException;
|
||||
abstract Set<DBRecord> getRelatedAssociationRecordsByDestinationAddress(
|
||||
long destinationAddressID) throws IOException;
|
||||
|
||||
abstract void updateRecord(DBRecord record) throws IOException;
|
||||
|
||||
|
@ -16,16 +16,16 @@
|
||||
package ghidra.feature.vt.api.db;
|
||||
|
||||
import static ghidra.feature.vt.api.db.VTAssociationTableDBAdapter.AssociationTableDescriptor.*;
|
||||
import ghidra.feature.vt.api.main.VTAssociationStatus;
|
||||
import ghidra.feature.vt.api.main.VTAssociationType;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import db.*;
|
||||
import ghidra.feature.vt.api.main.VTAssociationStatus;
|
||||
import ghidra.feature.vt.api.main.VTAssociationType;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class VTAssociationTableDBAdapterV0 extends VTAssociationTableDBAdapter {
|
||||
|
||||
@ -81,14 +81,14 @@ public class VTAssociationTableDBAdapterV0 extends VTAssociationTableDBAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator getRecordsForDestinationAddress(long addressID) throws IOException {
|
||||
LongField longField = new LongField(addressID);
|
||||
RecordIterator getRecordsForDestinationAddress(long addressId) throws IOException {
|
||||
LongField longField = new LongField(addressId);
|
||||
return table.indexIterator(DESTINATION_ADDRESS_COL.column(), longField, longField, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator getRecordsForSourceAddress(long addressID) throws IOException {
|
||||
LongField longField = new LongField(addressID);
|
||||
RecordIterator getRecordsForSourceAddress(long addressId) throws IOException {
|
||||
LongField longField = new LongField(addressId);
|
||||
return table.indexIterator(SOURCE_ADDRESS_COL.column(), longField, longField, true);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,8 @@ import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.*;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTChangeManager {
|
||||
private final static Field[] COL_FIELDS = new Field[] { StringField.INSTANCE };
|
||||
@ -61,7 +62,7 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
* database schema associated with any of the adapters.
|
||||
* 14-Nov-2019 - version 2 - Corrected fixed length indexing implementation causing
|
||||
* change in index table low-level storage for newly
|
||||
* created tables.
|
||||
* created tables.
|
||||
*/
|
||||
private static final int DB_VERSION = 2;
|
||||
|
||||
@ -287,6 +288,8 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
throw new RuntimeException(buffer.toString());
|
||||
}
|
||||
|
||||
associationManager.sessionInitialized();
|
||||
|
||||
try {
|
||||
addSynchronizedDomainObject(destinationProgram);
|
||||
}
|
||||
@ -324,9 +327,6 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.framework.data.DomainObjectAdapterDB#clearCache()
|
||||
*/
|
||||
@Override
|
||||
protected void clearCache(boolean all) {
|
||||
lock.acquire();
|
||||
@ -354,7 +354,7 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
try {
|
||||
save(DESTINATION_PROGRAM_ID_PROPERTY_KEY, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
save(DESTINATION_PROGRAM_ID_PROPERTY_KEY, TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// can't happen because we are using a dummy monitor
|
||||
@ -476,7 +476,7 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
return associationManager;
|
||||
}
|
||||
|
||||
/** Package-level methods for accessing DB-related manager */
|
||||
/* Package-level methods for accessing DB-related manager */
|
||||
public AssociationDatabaseManager getAssociationManagerDBM() {
|
||||
return associationManager;
|
||||
}
|
||||
@ -508,9 +508,6 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
|
||||
@Override
|
||||
public void setChanged(int type, Object oldValue, Object newValue) {
|
||||
// if (recordChanges) {
|
||||
// updateChangeSet(newstart, newend);
|
||||
// }
|
||||
changed = true;
|
||||
|
||||
fireEvent(new VersionTrackingChangeRecord(type, null, oldValue, newValue));
|
||||
@ -528,9 +525,6 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
@Override
|
||||
public void setObjectChanged(int type, Object affectedObject, Object oldValue,
|
||||
Object newValue) {
|
||||
// if (recordChanges) {
|
||||
// updateChangeSet(newstart, newend);
|
||||
// }
|
||||
changed = true;
|
||||
|
||||
fireEvent(new VersionTrackingChangeRecord(type, affectedObject, oldValue, newValue));
|
||||
@ -716,4 +710,9 @@ public class VTSessionDB extends DomainObjectAdapterDB implements VTSession, VTC
|
||||
associationManager.removeAssociationHook(hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
associationManager.dispose();
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,6 +15,14 @@
|
||||
*/
|
||||
package ghidra.feature.vt.api.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import db.DBHandle;
|
||||
import db.OpenMode;
|
||||
import db.buffers.BufferFile;
|
||||
import ghidra.feature.vt.api.db.VTSessionDB;
|
||||
import ghidra.framework.data.*;
|
||||
import ghidra.framework.model.ChangeSet;
|
||||
@ -26,38 +33,30 @@ import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import resources.ResourceManager;
|
||||
import db.DBHandle;
|
||||
import db.OpenMode;
|
||||
import db.buffers.BufferFile;
|
||||
|
||||
public class VTSessionContentHandler extends DBContentHandler {
|
||||
private static ImageIcon ICON = ResourceManager.getScaledIcon(
|
||||
ResourceManager.loadImage("images/start-here_16.png"), 16, 16);
|
||||
private static ImageIcon ICON = ResourceManager
|
||||
.getScaledIcon(ResourceManager.loadImage("images/start-here_16.png"), 16, 16);
|
||||
|
||||
public final static String CONTENT_TYPE = "VersionTracking";
|
||||
|
||||
@Override
|
||||
public long createFile(FileSystem fs, FileSystem userfs, String path, String name,
|
||||
DomainObject domainObject, TaskMonitor monitor) throws IOException,
|
||||
InvalidNameException, CancelledException {
|
||||
DomainObject domainObject, TaskMonitor monitor)
|
||||
throws IOException, InvalidNameException, CancelledException {
|
||||
|
||||
if (!(domainObject instanceof VTSessionDB)) {
|
||||
throw new IOException("Unsupported domain object: " + domainObject.getClass().getName());
|
||||
throw new IOException(
|
||||
"Unsupported domain object: " + domainObject.getClass().getName());
|
||||
}
|
||||
return createFile((VTSessionDB) domainObject, CONTENT_TYPE, fs, path, name, monitor);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeSet getChangeSet(FolderItem versionedFolderItem, int olderVersion, int newerVersion)
|
||||
throws VersionException, IOException {
|
||||
public ChangeSet getChangeSet(FolderItem versionedFolderItem, int olderVersion,
|
||||
int newerVersion) throws VersionException, IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -133,8 +132,8 @@ public class VTSessionContentHandler extends DBContentHandler {
|
||||
|
||||
@Override
|
||||
public DomainObjectAdapter getImmutableObject(FolderItem item, Object consumer, int version,
|
||||
int minChangeVersion, TaskMonitor monitor) throws IOException, CancelledException,
|
||||
VersionException {
|
||||
int minChangeVersion, TaskMonitor monitor)
|
||||
throws IOException, CancelledException, VersionException {
|
||||
|
||||
String contentType = item.getContentType();
|
||||
if (!contentType.equals(CONTENT_TYPE)) {
|
||||
@ -145,16 +144,16 @@ public class VTSessionContentHandler extends DBContentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainObjectMergeManager getMergeManager(DomainObject resultsObj,
|
||||
DomainObject sourceObj, DomainObject originalObj, DomainObject latestObj) {
|
||||
public DomainObjectMergeManager getMergeManager(DomainObject resultsObj, DomainObject sourceObj,
|
||||
DomainObject originalObj, DomainObject latestObj) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainObjectAdapter getReadOnlyObject(FolderItem item, int version, boolean okToUpgrade,
|
||||
Object consumer, TaskMonitor monitor) throws IOException, VersionException,
|
||||
CancelledException {
|
||||
Object consumer, TaskMonitor monitor)
|
||||
throws IOException, VersionException, CancelledException {
|
||||
|
||||
String contentType = item.getContentType();
|
||||
if (contentType != null && !contentType.equals(CONTENT_TYPE)) {
|
||||
@ -181,7 +180,7 @@ public class VTSessionContentHandler extends DBContentHandler {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
Msg.error(this, "getImmutableObject failed", t);
|
||||
Msg.error(this, "Get read-only object failed", t);
|
||||
String msg = t.getMessage();
|
||||
if (msg == null) {
|
||||
msg = t.toString();
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,7 +16,7 @@
|
||||
package ghidra.feature.vt.api.main;
|
||||
|
||||
/**
|
||||
* Interface used for a callback when associations are accepted or cleared.
|
||||
* Interface used for a callback when associations are accepted or cleared.
|
||||
*/
|
||||
public interface AssociationHook {
|
||||
/**
|
||||
@ -28,7 +27,7 @@ public interface AssociationHook {
|
||||
|
||||
/**
|
||||
* Called whenever an association has been cleared from the accepted state.
|
||||
* @param association the association that has been cleared from the accpeted state.
|
||||
* @param association the association that has been cleared from the accepted state.
|
||||
*/
|
||||
public void associationCleared(VTAssociation association);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,15 +15,15 @@
|
||||
*/
|
||||
package ghidra.feature.vt.api.main;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.feature.vt.api.util.VTAssociationStatusException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A VTAssociation is a possible equivalence between a function or data in one program to
|
||||
* A VTAssociation is a possible equivalence between a function or data in one program to
|
||||
* a function or data in another program. VTAssociations can be "Accepted" indicating that
|
||||
* the user has agreed that the association is correct.
|
||||
*/
|
||||
@ -72,23 +71,24 @@ public interface VTAssociation {
|
||||
|
||||
/**
|
||||
* Returns a collection of VTAssociations that have either the same source address or the same
|
||||
* destination address.
|
||||
* destination address.
|
||||
* @return a collection of VTAssociations that have either the same source address or the same
|
||||
* destination address.
|
||||
*/
|
||||
public Collection<VTAssociation> getRelatedAssociations();
|
||||
|
||||
/**
|
||||
* Sets the markup status of this association. This method is used by the
|
||||
* Sets the markup status of this association. This method is used by the
|
||||
* {@link VTAssociationManager} to update the association with information about the state
|
||||
* of its markup items.
|
||||
* @param markupItemsStatus the markup items
|
||||
*/
|
||||
public void setMarkupStatus(VTAssociationMarkupStatus markupItemsStatus);
|
||||
|
||||
/**
|
||||
* Returns the status of the markup items for this association.
|
||||
* Returns the status of the markup items for this association.
|
||||
* See {@link VTAssociationMarkupStatus} for details.
|
||||
*
|
||||
*
|
||||
* @return the status of the markup items for this association.
|
||||
*/
|
||||
public VTAssociationMarkupStatus getMarkupStatus();
|
||||
@ -102,25 +102,23 @@ public interface VTAssociation {
|
||||
|
||||
/**
|
||||
* A convenience method to accept the given association without actually performing an apply.
|
||||
*
|
||||
* @param association the association to accept
|
||||
* @throws VTAssociationStatusException if the given association is
|
||||
*
|
||||
* @throws VTAssociationStatusException if the given association is
|
||||
* {@link VTAssociationStatus#BLOCKED}
|
||||
*/
|
||||
public void setAccepted() throws VTAssociationStatusException;
|
||||
|
||||
/**
|
||||
* Clears the state of the given association from {@link VTAssociationStatus#ACCEPTED}
|
||||
* or {@link VTAssociationStatus#REJECTED} to {@link VTAssociationStatus#AVAILABLE}.
|
||||
* This method will throw an exception if called while the given assocation's markup items
|
||||
* have been applied. That is, you must first unapply any applied markup items before
|
||||
* calling this method.
|
||||
*
|
||||
* @param association the association whose state will be changed
|
||||
* @throws VTAssociationStatusException if the given association's status is not
|
||||
* {@link VTAssociationStatus#ACCEPTED}/{@link VTAssociationStatus#REJECTED}
|
||||
* <b>or</b> if the given assocation's
|
||||
* {@link VTMarkupItemManager} contains markup items that have been applied.
|
||||
* or {@link VTAssociationStatus#REJECTED} to {@link VTAssociationStatus#AVAILABLE}.
|
||||
* This method will throw an exception if called while the given assocation's markup items
|
||||
* have been applied. That is, you must first unapply any applied markup items before
|
||||
* calling this method.
|
||||
*
|
||||
* @throws VTAssociationStatusException if the given association's status is not
|
||||
* {@link VTAssociationStatus#ACCEPTED}/{@link VTAssociationStatus#REJECTED}
|
||||
* <b>or</b> if the given assocation's markup item manager contains markup items that
|
||||
* have been applied.
|
||||
*/
|
||||
public void clearStatus() throws VTAssociationStatusException;
|
||||
|
||||
@ -132,9 +130,9 @@ public interface VTAssociation {
|
||||
|
||||
/**
|
||||
* Returns the current vote count which is an application settable field which should generally
|
||||
* be used to indicate a number of supporting facts. For example, other accepted assocations
|
||||
* be used to indicate a number of supporting facts. For example, other accepted associations
|
||||
* may have matching call references to this association, each of those matching calls should
|
||||
* have incremented the votes.
|
||||
* have incremented the votes.
|
||||
* @return the current number of facts that support this association
|
||||
*/
|
||||
public int getVoteCount();
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,14 +15,14 @@
|
||||
*/
|
||||
package ghidra.feature.vt.api.main;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
/**
|
||||
* The interface for the association manager which manages the associations which are shared
|
||||
* with similar matches within a session.
|
||||
* with similar matches within a session.
|
||||
*
|
||||
*/
|
||||
public interface VTAssociationManager {
|
||||
@ -60,7 +59,7 @@ public interface VTAssociationManager {
|
||||
|
||||
/**
|
||||
* Returns a collection of all defined associations that have the given destination address.
|
||||
* @param destinaitionAddress the source address to use to search for associations.
|
||||
* @param destinationAddress the source address to use to search for associations.
|
||||
* @return a collection of all defined associations that have the given destination address.
|
||||
*/
|
||||
public Collection<VTAssociation> getRelatedAssociationsByDestinationAddress(
|
||||
@ -70,11 +69,10 @@ public interface VTAssociationManager {
|
||||
* Returns a collection of all defined associations that have the either the given source
|
||||
* address or the given destination address
|
||||
* @param sourceAddress the source address to use to search for associations.
|
||||
* @param destinaitionAddress the source address to use to search for associations.
|
||||
* @param destinationAddress the source address to use to search for associations.
|
||||
* @return a collection of all defined associations that have either the given source
|
||||
* address or the given destination address.
|
||||
*/
|
||||
public Collection<VTAssociation> getRelatedAssociationsBySourceAndDestinationAddress(
|
||||
Address sourceAddress, Address destinationAddress);
|
||||
|
||||
}
|
||||
|
@ -40,30 +40,30 @@ import ghidra.util.task.TaskMonitor;
|
||||
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):
|
||||
* <ol>
|
||||
* <li> Exact Symbol Name correlator </li>
|
||||
* <li> Exact Data correlator </li>
|
||||
* <li> Exact Function Byte correlator </li>
|
||||
* <li> Exact Function Byte correlator </li>
|
||||
* <li> Exact Function Instruction correlator </li>
|
||||
* <li> Exact Function Mnemonic correlator </li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <P> After running each correlator all matches are accepted since they are exact/unique matches
|
||||
* and all markup from the source program functions is applied to the matching destination program
|
||||
* functions.
|
||||
*
|
||||
* <P> Next, this command runs the Duplicate Function Instruction correlator to find any non-unique
|
||||
* functions with exact instruction bytes then compares their operands to determine and accept
|
||||
* correct matches with markup.
|
||||
*
|
||||
* <P> The command then gets a little more speculative by running the Combined Function and Data
|
||||
* Reference correlator, which uses match information from the previous correlators to find more
|
||||
* matches.
|
||||
*
|
||||
*
|
||||
* <P> Next, this command runs the Duplicate Function Instruction correlator to find any non-unique
|
||||
* functions with exact instruction bytes then compares their operands to determine and accept
|
||||
* correct matches with markup.
|
||||
*
|
||||
* <P> The command then gets a little more speculative by running the Combined Function and Data
|
||||
* Reference correlator, which uses match information from the previous correlators to find more
|
||||
* matches.
|
||||
*
|
||||
* <P> As more techniques get developed, more automation will be added to this command.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
@ -82,14 +82,14 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* Constructor for AutoVersionTrackingCommand
|
||||
*
|
||||
*
|
||||
* @param controller The Version Tracking controller for this session containing option and
|
||||
* tool information needed for this command.
|
||||
* @param session The Version Tracking session containing the source, destination, correlator
|
||||
* and match information needed for this command.
|
||||
* @param session The Version Tracking session containing the source, destination, correlator
|
||||
* and match information needed for this command.
|
||||
* @param minCombinedReferenceCorrelatorScore The minimum score used to limit matches created by
|
||||
* the Combined Reference Correlator.
|
||||
* @param minCombinedReferenceCorrelatorConfidence The minimum confidence used to limit matches
|
||||
* @param minCombinedReferenceCorrelatorConfidence The minimum confidence used to limit matches
|
||||
* created by the Combined Reference Correlator.
|
||||
*/
|
||||
public AutoVersionTrackingCommand(VTController controller, VTSession session,
|
||||
@ -117,11 +117,11 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
monitor.initialize(NUM_CORRELATORS);
|
||||
|
||||
// Use default options for all of the "exact" correlators and passed in options for
|
||||
// the others.
|
||||
// the others.
|
||||
VTOptions options;
|
||||
|
||||
// Run the correlators in the following order:
|
||||
// Do this one first because we don't want it to find ones that get markup
|
||||
// Run the correlators in the following order:
|
||||
// Do this one first because we don't want it to find ones that get markup
|
||||
// applied by later correlators
|
||||
VTProgramCorrelatorFactory factory = new SymbolNameProgramCorrelatorFactory();
|
||||
options = factory.createDefaultOptions();
|
||||
@ -145,10 +145,10 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
// 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
|
||||
// than one possible match for each function. The compare mechanism used by the
|
||||
// function compare window determines matches based on matching operand values.
|
||||
// Given that each function must contains the same instructions to even become a match,
|
||||
// and the compare function mechanism has been very well tested, the mechanism for
|
||||
// than one possible match for each function. The compare mechanism used by the
|
||||
// function compare window determines matches based on matching operand values.
|
||||
// Given that each function must contains the same instructions to even become a match,
|
||||
// and the compare function mechanism has been very well tested, the mechanism for
|
||||
// finding the correct match is very accurate.
|
||||
factory = new DuplicateFunctionMatchProgramCorrelatorFactory();
|
||||
options = factory.createDefaultOptions();
|
||||
@ -157,11 +157,11 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
// The rest are mores speculative matching algorithms because they depend on our
|
||||
// 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
|
||||
// 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
|
||||
String confidenceOption =
|
||||
VTAbstractReferenceProgramCorrelatorFactory.CONFIDENCE_THRESHOLD;
|
||||
@ -171,7 +171,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
int numDataMatches = getNumberOfDataMatches(monitor);
|
||||
int numFunctionMatches = getNumberOfFunctionMatches(monitor);
|
||||
|
||||
// Run the DataReferenceCorrelator if there are accepted data matches but no accepted
|
||||
// Run the DataReferenceCorrelator if there are accepted data matches but no accepted
|
||||
// function matches
|
||||
if (numDataMatches > 0 && numFunctionMatches == 0) {
|
||||
factory = new DataReferenceProgramCorrelatorFactory();
|
||||
@ -269,12 +269,12 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given version tracking (VT) correlator and applies the returned matches meeting the
|
||||
* Runs the given version tracking (VT) correlator and applies the returned matches meeting the
|
||||
* given score and confidence thresholds and are not otherwise blocked.
|
||||
* @param factory The correlator factory used to create and run the desired VT correlator.
|
||||
* @param options The options to pass the correlator including score and confidence values.
|
||||
* @param monitor Checks to see if user has cancelled.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private boolean correlateAndPossiblyApply(VTProgramCorrelatorFactory factory, VTOptions options,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
@ -299,14 +299,14 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* Runs the Duplicate Exact Function match version tracking (VT) correlator then determines
|
||||
* correct matches based on matching operand values. Those matches are accepted and other
|
||||
* correct matches based on matching operand values. Those matches are accepted and other
|
||||
* possible matches for those functions are blocked. Markup from accepted source functions
|
||||
* is applied to matching destination functions.
|
||||
* is applied to matching destination functions.
|
||||
*
|
||||
* @param factory The correlator factory used to create and run the desired VT correlator. In
|
||||
* @param factory The correlator factory used to create and run the desired VT correlator. In
|
||||
* this case, the duplicate function instruction match correlator.
|
||||
* @param monitor Checks to see if user has cancelled.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private boolean correlateAndPossiblyApplyDuplicateFunctions(VTProgramCorrelatorFactory factory,
|
||||
VTOptions options, TaskMonitor monitor) throws CancelledException {
|
||||
@ -326,14 +326,14 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called for all correlators that are run by this command except the duplicate function
|
||||
* instruction match correlator.
|
||||
* @param matches The set of matches to try to accept as matches.
|
||||
* @param correlatorName The name of the Version Tracking correlator whose matches are being
|
||||
* applied here.
|
||||
* Called for all correlators that are run by this command except the duplicate function
|
||||
* instruction match correlator.
|
||||
* @param matches The set of matches to try to accept as matches.
|
||||
* @param correlatorName The name of the Version Tracking correlator whose matches are being
|
||||
* applied here.
|
||||
* @param monitor Checks to see if user has cancelled.
|
||||
* @return true if some matches have markup errors and false if none have markup errors.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private boolean applyMatches(Collection<VTMatch> matches, String correlatorName,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
@ -341,7 +341,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
// If this value gets set to true then there are some markup errors in the whole set of
|
||||
// matches.
|
||||
boolean someMatchesHaveMarkupErrors = false;
|
||||
// Note: no need to check score/confidence because they are passed into the correlator
|
||||
// Note: no need to check score/confidence because they are passed into the correlator
|
||||
// ahead of time so correlator only returns matches higher than given score/threshold
|
||||
for (VTMatch match : matches) {
|
||||
monitor.checkCanceled();
|
||||
@ -376,7 +376,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* This method tries to set a match association as accepted.
|
||||
* @param association The match association between two match items.
|
||||
* @param association The match association between two match items.
|
||||
* @return true if match is accepted and false if an exception occurred and the match couldn't be
|
||||
* accepted.
|
||||
*/
|
||||
@ -394,13 +394,13 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 operands
|
||||
* if they are a unique match within their associated set.
|
||||
* @param matches A collection of version tracking matches from the duplicate instruction
|
||||
* matcher.
|
||||
* @param matches A collection of version tracking matches from the duplicate instruction
|
||||
* matcher.
|
||||
* @param monitor Allows user to cancel
|
||||
* @return true if any markup errors, false if no markup errors.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private boolean applyDuplicateFunctionMatches(Collection<VTMatch> matches, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
@ -413,34 +413,34 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
for (VTMatch match : matches) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
// if match has already been removed (ie it was in a set that was already processed)
|
||||
// if match has already been removed (ie it was in a set that was already processed)
|
||||
// then skip it
|
||||
if (!copyOfMatches.contains(match)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get a set of related matches from the set of all matches
|
||||
// ie these all have the same instructions as each other but not necessarily
|
||||
// ie these all have the same instructions as each other but not necessarily
|
||||
// the same operands.
|
||||
Set<VTMatch> relatedMatches = getRelatedMatches(match, matches, monitor);
|
||||
|
||||
// remove related matches from the set of matches to process next time
|
||||
removeMatches(copyOfMatches, relatedMatches);
|
||||
|
||||
// remove any matches that have identical source functions - if more than one
|
||||
// remove any matches that have identical source functions - if more than one
|
||||
// with exactly the same instructions and operands then cannot determine a unique match
|
||||
Set<Address> sourceAddresses = getSourceAddressesFromMatches(relatedMatches, monitor);
|
||||
Set<Address> uniqueSourceFunctionAddresses =
|
||||
dedupeMatchingFunctions(sourceProgram, sourceAddresses, monitor);
|
||||
dedupMatchingFunctions(sourceProgram, sourceAddresses, monitor);
|
||||
|
||||
// remove any matches that have identical destination functions - if more than one
|
||||
// remove any matches that have identical destination functions - if more than one
|
||||
// with exactly the same instructions and operands then cannot determine a unique match
|
||||
Set<Address> destAddresses =
|
||||
getDestinationAddressesFromMatches(relatedMatches, monitor);
|
||||
Set<Address> uniqueDestFunctionAddresses =
|
||||
dedupeMatchingFunctions(destinationProgram, destAddresses, monitor);
|
||||
dedupMatchingFunctions(destinationProgram, destAddresses, monitor);
|
||||
|
||||
//Keep only matches containing the unique sources and destination functions determined above
|
||||
// Keep only matches containing the unique sources and destination functions determined above
|
||||
Set<VTMatch> dedupedMatches = getMatches(relatedMatches, uniqueSourceFunctionAddresses,
|
||||
uniqueDestFunctionAddresses, monitor);
|
||||
|
||||
@ -448,14 +448,15 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
for (Address sourceAddress : uniqueSourceFunctionAddresses) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
//Find all destination functions with equivalent operands to current source function
|
||||
// Find all destination functions with equivalent operands to current source function
|
||||
Set<VTMatch> matchesWithEquivalentOperands = getMatchesWithEquivalentOperands(
|
||||
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) {
|
||||
VTMatch theMatch = CollectionUtils.any(matchesWithEquivalentOperands);
|
||||
someMatchesHaveMarkupErrors = tryToAcceptMatchAndApplyMarkup(theMatch, monitor);
|
||||
someMatchesHaveMarkupErrors |=
|
||||
tryToAcceptMatchAndApplyMarkup(theMatch, monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -505,7 +506,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
* @param destAddresses Addresses of destination functions to compare with source function
|
||||
* @param monitor Allows user to cancel
|
||||
* @return Set of all matches with equivalent operands.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private Set<VTMatch> getMatchesWithEquivalentOperands(Set<VTMatch> matches,
|
||||
Address sourceAddress, Set<Address> destAddresses, TaskMonitor monitor)
|
||||
@ -526,13 +527,13 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine which matches from a collection of matches are related to the given match, ie
|
||||
* have the same source or destination address as the current match.
|
||||
* Determine which matches from a collection of matches are related to the given match, ie
|
||||
* have the same source or destination address as the current match.
|
||||
* @param match Current version tracking match
|
||||
* @param matches Collection version tracking matches
|
||||
* @param monitor Allows user to cancel
|
||||
* @return Set of matches related to the given match
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private Set<VTMatch> getRelatedMatches(VTMatch match, Collection<VTMatch> matches,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
@ -562,7 +563,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* Remove given matches from a set of matches.
|
||||
* @param matchSet Set of matches.
|
||||
* @param matchSet Set of matches.
|
||||
* @param matchesToRemove Set of matches to remove from matches set.
|
||||
*/
|
||||
private void removeMatches(Set<VTMatch> matchSet, Set<VTMatch> matchesToRemove) {
|
||||
@ -581,7 +582,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
* @param matches Set of version tracking matches
|
||||
* @param monitor Allows user to cancel
|
||||
* @return A set of source addresses from the given set of version tracking matches.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private Set<Address> getSourceAddressesFromMatches(Set<VTMatch> matches, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
@ -599,7 +600,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
* @param matches Set of version tracking matches
|
||||
* @param monitor Allows user to cancel
|
||||
* @return A set of destination addresses from the given set of version tracking matches.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private Set<Address> getDestinationAddressesFromMatches(Set<VTMatch> matches,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
@ -632,13 +633,13 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* From a set of matches get the subset that contains the given source and destination addresses.
|
||||
* From a set of matches get the subset that contains the given source and destination addresses.
|
||||
* @param matches Set of matches
|
||||
* @param sourceAddresses Set of source addresses
|
||||
* @param destAddresses Set of destination addresses
|
||||
* @param monitor Allows user to cancel
|
||||
* @return Set of matches containing given source and destination addresses.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private Set<VTMatch> getMatches(Set<VTMatch> matches, Set<Address> sourceAddresses,
|
||||
Set<Address> destAddresses, TaskMonitor monitor) throws CancelledException {
|
||||
@ -656,18 +657,18 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* * This method is only called to compare functions with identical instruction
|
||||
* bytes, identical operand lengths, but possibly different operand values. It returns true
|
||||
* if the two functions in the match have potentially equivalent operands. It returns false if
|
||||
* any of the operands do not match.
|
||||
* bytes, identical operand lengths, but possibly different operand values. It returns true
|
||||
* if the two functions in the match have potentially equivalent operands. It returns false if
|
||||
* any of the operands do not match.
|
||||
* Potentially equivalent means corresponding scalar operands match, corresponding other operands have
|
||||
* the same type of operand (ie code, data,register)
|
||||
* the same type of operand (i.e., code, data,register)
|
||||
* @param program1 Program containing function1
|
||||
* @param function1 Function to compare with function2
|
||||
* @param address1 Function to compare with function2
|
||||
* @param program2 Program containing function2
|
||||
* @param function2 Function to compare with function1
|
||||
* @param address2 Function to compare with function1
|
||||
* @param monitor Allows user to cancel
|
||||
* @return true if all operands between the two functions match and false otherwise.
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private boolean haveEquivalentOperands(Program program1, Address address1, Program program2,
|
||||
Address address2, TaskMonitor monitor) throws CancelledException {
|
||||
@ -703,7 +704,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
// This should never happen but if it does then throw an error because that means something
|
||||
// weird is happening like the action updating the source and destination match lengths
|
||||
// weird is happening like the action updating the source and destination match lengths
|
||||
// didn't do it correctly.
|
||||
if (func1InstIter.hasNext() || func2InstIter.hasNext()) {
|
||||
throw new AssertException(
|
||||
@ -716,11 +717,11 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* Determine if the given instructions which have at least one differing operand, have equivalent
|
||||
* operand types. If operand type is a scalar, is it the same scalar.
|
||||
* operand types. If operand type is a scalar, is it the same scalar.
|
||||
* @param inst1 Instruction 1
|
||||
* @param inst2 Instruction 2
|
||||
* @param operandsThatDiffer Array of indexes of operands that differ
|
||||
* @return true if all operands in the two instructions are equivalent types and scalars are equal,
|
||||
* @return true if all operands in the two instructions are equivalent types and scalars are equal,
|
||||
* else return false
|
||||
*/
|
||||
private boolean haveEquivalentOperands(Instruction inst1, Instruction inst2,
|
||||
@ -761,14 +762,14 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* Method to determine if two functions with exactly the same instructions also have exactly the
|
||||
* same operands.
|
||||
* same operands.
|
||||
* @param program1 Program that contains function1
|
||||
* @param function1 Function to compare with function2
|
||||
* @param program2 Program that contains function2 (can be same or different than program1)
|
||||
* @param program2 Program that contains function2 (can be same or different than program1)
|
||||
* @param function2 Function to compare with function1
|
||||
* @param monitor
|
||||
* @param monitor the monitor
|
||||
* @return true if two functions have no operand differences, else returns false
|
||||
* @throws CancelledException
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
private boolean haveSameOperands(Program program1, Function function1, Program program2,
|
||||
Function function2, TaskMonitor monitor) throws CancelledException {
|
||||
@ -795,7 +796,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
}
|
||||
}
|
||||
// This should never happen but if it does then throw an error because that means something
|
||||
// weird is happening like the action updating the source and destination match lengths
|
||||
// weird is happening like the action updating the source and destination match lengths
|
||||
// didn't do it correctly.
|
||||
if (sourceFuncCodeUnitIter.hasNext() || destFuncCodeUnitIter.hasNext()) {
|
||||
throw new AssertException(
|
||||
@ -807,14 +808,13 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
/**
|
||||
* Remove addresses from a set of function starting addresses if any functions have all matching
|
||||
* operands.
|
||||
* @param program Program containing functions we are interested in deduping.
|
||||
* @param addresses Set of function start addresses.
|
||||
* @param functionManager Function manager to get functions using their start addresses.
|
||||
* @param monitor
|
||||
* @return Set of addresses of deduped function bytes.
|
||||
* @throws CancelledException
|
||||
* @param program the program
|
||||
* @param addresses Set of function start addresses
|
||||
* @param monitor the monitor
|
||||
* @return Set of addresses of deduped function bytes
|
||||
* @throws CancelledException if cancelled
|
||||
*/
|
||||
public Set<Address> dedupeMatchingFunctions(Program program, Set<Address> addresses,
|
||||
public Set<Address> dedupMatchingFunctions(Program program, Set<Address> addresses,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
@ -824,7 +824,7 @@ public class AutoVersionTrackingCommand extends BackgroundCommand {
|
||||
|
||||
List<Address> list = new ArrayList<>(addresses);
|
||||
|
||||
// Compare 0 to 1, 0 to 2, ... 0 to j-1, 1 to 2, 1 to 3, ... 1- j-1, .... i-2 to j-1
|
||||
// Compare 0 to 1, 0 to 2, ... 0 to j-1, 1 to 2, 1 to 3, ... 1- j-1, .... i-2 to j-1
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
Address address1 = list.get(i);
|
||||
|
@ -54,7 +54,7 @@ public class AddressCorrelatorManager {
|
||||
}
|
||||
|
||||
private void initializeAddressCorrelators(VTController controller) {
|
||||
// Put the CodeCompare address correlator that uses match info to handle exact matches
|
||||
// Put the CodeCompare address correlator that uses match info to handle exact matches
|
||||
// so it is first in the list.
|
||||
correlatorList.add(new ExactMatchAddressCorrelator(controller));
|
||||
correlatorList.addAll(initializeAddressCorrelators());
|
||||
|
@ -73,8 +73,10 @@ public class VTControllerImpl
|
||||
vtOptions = plugin.getTool().getOptions(VERSION_TRACKING_OPTIONS_NAME);
|
||||
vtOptions.addOptionsChangeListener(this);
|
||||
folderListener = new MyFolderListener();
|
||||
plugin.getTool().getProject().getProjectData().addDomainFolderChangeListener(
|
||||
folderListener);
|
||||
plugin.getTool()
|
||||
.getProject()
|
||||
.getProjectData()
|
||||
.addDomainFolderChangeListener(folderListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -98,8 +100,8 @@ public class VTControllerImpl
|
||||
return;
|
||||
}
|
||||
try {
|
||||
VTSessionDB newSession = (VTSessionDB) domainFile.getDomainObject(this, true, true,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
VTSessionDB newSession =
|
||||
(VTSessionDB) domainFile.getDomainObject(this, true, true, TaskMonitor.DUMMY);
|
||||
doOpenSession(newSession);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
@ -476,9 +478,11 @@ public class VTControllerImpl
|
||||
return;
|
||||
}
|
||||
|
||||
WrapperTask wrappedTask = new WrapperTask(task);
|
||||
|
||||
int matchSetTransactionID = session.startTransaction(task.getTaskTitle());
|
||||
try {
|
||||
new TaskLauncher(task, getParentComponent());
|
||||
new TaskLauncher(wrappedTask, getParentComponent());
|
||||
}
|
||||
finally {
|
||||
session.endTransaction(matchSetTransactionID, task.wasSuccessfull());
|
||||
@ -486,7 +490,6 @@ public class VTControllerImpl
|
||||
if (task.hasErrors()) {
|
||||
task.showErrors();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean hasTransactionsOpen(Program program, VtTask task) {
|
||||
@ -527,9 +530,45 @@ public class VTControllerImpl
|
||||
plugin.setSelectionInDestinationTool(destinationSet);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
@Override
|
||||
public Symbol getDestinationSymbol(VTAssociation association) {
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
Address address = association.getDestinationAddress();
|
||||
Symbol symbol = destinationSymbolCache.get(address);
|
||||
if (symbol == null) {
|
||||
Program program = session.getDestinationProgram();
|
||||
symbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||
destinationSymbolCache.put(address, symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol getSourceSymbol(VTAssociation association) {
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
Address address = association.getSourceAddress();
|
||||
Symbol symbol = sourceSymbolCache.get(address);
|
||||
if (symbol == null) {
|
||||
Program program = session.getSourceProgram();
|
||||
symbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||
sourceSymbolCache.put(address, symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorizingService getSourceColorizingService() {
|
||||
return plugin.getSourceColorizingService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorizingService getDestinationColorizingService() {
|
||||
return plugin.getDestinationColorizingService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transactionEnded(DomainObjectAdapterDB domainObj) {
|
||||
@ -552,6 +591,10 @@ public class VTControllerImpl
|
||||
// don't care
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
private class MyFolderListener extends DomainFolderListenerAdapter {
|
||||
|
||||
@Override
|
||||
@ -571,8 +614,7 @@ public class VTControllerImpl
|
||||
}
|
||||
Program newProgram;
|
||||
try {
|
||||
newProgram = (Program) file.getDomainObject(this, false, false,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
newProgram = (Program) file.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.showError(this, getParentComponent(), "Error opening program " + file, e);
|
||||
@ -630,43 +672,31 @@ public class VTControllerImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol getDestinationSymbol(VTAssociation association) {
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
Address address = association.getDestinationAddress();
|
||||
Symbol symbol = destinationSymbolCache.get(address);
|
||||
if (symbol == null) {
|
||||
Program program = session.getDestinationProgram();
|
||||
symbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||
destinationSymbolCache.put(address, symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
/**
|
||||
* A task wrapper that allows us to set the currently in-use task monitor for VT APIs to use
|
||||
* when they are not explicitly passed a task monitor.
|
||||
*/
|
||||
private class WrapperTask extends Task {
|
||||
|
||||
@Override
|
||||
public Symbol getSourceSymbol(VTAssociation association) {
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
Address address = association.getSourceAddress();
|
||||
Symbol symbol = sourceSymbolCache.get(address);
|
||||
if (symbol == null) {
|
||||
Program program = session.getSourceProgram();
|
||||
symbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||
sourceSymbolCache.put(address, symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
private final Task delegate;
|
||||
|
||||
@Override
|
||||
public ColorizingService getSourceColorizingService() {
|
||||
return plugin.getSourceColorizingService();
|
||||
}
|
||||
WrapperTask(Task t) {
|
||||
super(t.getTaskTitle(), t.canCancel(), t.hasProgress(), t.isModal(),
|
||||
t.getWaitForTaskCompleted());
|
||||
this.delegate = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
VTTaskMonitor.setTaskMonitor(monitor);
|
||||
try {
|
||||
delegate.run(monitor);
|
||||
}
|
||||
finally {
|
||||
VTTaskMonitor.setTaskMonitor(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorizingService getDestinationColorizingService() {
|
||||
return plugin.getDestinationColorizingService();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.plugin;
|
||||
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A class that allows the VT application to track the currently in-use task monitor. The
|
||||
* {@link VTController} will set this value each time it runs a VT task via
|
||||
* {@link VTController#runVTTask(ghidra.feature.vt.gui.task.VtTask)}.
|
||||
*
|
||||
* <p>In general, all background tasks should take a task monitor. However, some parts of the
|
||||
* VT API perform time-consuming work that does not require a task monitor. This exposes a
|
||||
* design flaw of the API. However, rather than add the task monitor to most API interfaces of
|
||||
* VT, we use this class to allow these poorly designed APIs to use the currently running task
|
||||
* monitor.
|
||||
*
|
||||
* <p>When using this monitor, it is expected that the client uses it only to check the state
|
||||
* of the cancelled flag. Other monitor operations, such as updating progress and setting
|
||||
* messages, are discouraged.
|
||||
*/
|
||||
public class VTTaskMonitor {
|
||||
|
||||
private static TaskMonitor monitor = TaskMonitor.DUMMY;
|
||||
|
||||
static void setTaskMonitor(TaskMonitor m) {
|
||||
monitor = TaskMonitor.dummyIfNull(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current in-use task monitor or a dummy monitor if there is no task running
|
||||
* @return the monitor
|
||||
*/
|
||||
public static TaskMonitor getTaskMonitor() {
|
||||
return monitor;
|
||||
}
|
||||
}
|
@ -116,7 +116,7 @@ class VTFunctionAssociationTableModel extends AddressBasedTableModel<VTFunctionR
|
||||
addObject(new VTFunctionRowObject(getInitializedFunctionInfo(function)));
|
||||
|
||||
// assumption: added functions did not exist and thus could not have been the basis for
|
||||
// a match. Thus, we don't have to add the new function to the
|
||||
// a match. Thus, we don't have to add the new function to the
|
||||
// collection of matched functions.
|
||||
}
|
||||
|
||||
@ -129,8 +129,8 @@ class VTFunctionAssociationTableModel extends AddressBasedTableModel<VTFunctionR
|
||||
associationManager.getRelatedAssociationsBySourceAddress(function.getEntryPoint());
|
||||
}
|
||||
else {
|
||||
associations = associationManager.getRelatedAssociationsByDestinationAddress(
|
||||
function.getEntryPoint());
|
||||
associations = associationManager
|
||||
.getRelatedAssociationsByDestinationAddress(function.getEntryPoint());
|
||||
|
||||
}
|
||||
boolean isInAssociation = !associations.isEmpty();
|
||||
@ -245,7 +245,6 @@ class VTFunctionAssociationTableModel extends AddressBasedTableModel<VTFunctionR
|
||||
Function getFunction(int row) {
|
||||
VTFunctionRowObject rowObject = getRowObject(row);
|
||||
FunctionAssociationInfo info = rowObject.getInfo();
|
||||
Program program = getProgram();
|
||||
FunctionManager manager = program.getFunctionManager();
|
||||
return manager.getFunction(info.getFunctionID());
|
||||
}
|
||||
@ -264,25 +263,23 @@ class VTFunctionAssociationTableModel extends AddressBasedTableModel<VTFunctionR
|
||||
@Override
|
||||
protected void doLoad(Accumulator<VTFunctionRowObject> accumulator, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
LongIterator it = LongIterator.EMPTY;
|
||||
|
||||
if (getProgram() != null) {
|
||||
FunctionManager functionManager = getProgram().getFunctionManager();
|
||||
it = new FunctionKeyIterator(functionManager);
|
||||
|
||||
monitor.initialize(getKeyCount());
|
||||
while (it.hasNext()) {
|
||||
monitor.incrementProgress(1);
|
||||
monitor.checkCanceled();
|
||||
long key = it.next();
|
||||
|
||||
Function f = functionManager.getFunction(key);
|
||||
if (!f.isThunk()) {
|
||||
accumulator.add(new VTFunctionRowObject(new FunctionAssociationInfo(key)));
|
||||
}
|
||||
}
|
||||
if (program == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.initialize(getKeyCount());
|
||||
FunctionManager functionManager = getProgram().getFunctionManager();
|
||||
LongIterator it = new FunctionKeyIterator(functionManager);
|
||||
while (it.hasNext()) {
|
||||
monitor.incrementProgress(1);
|
||||
monitor.checkCanceled();
|
||||
long key = it.next();
|
||||
Function f = functionManager.getFunction(key);
|
||||
if (!f.isThunk()) {
|
||||
accumulator.add(new VTFunctionRowObject(new FunctionAssociationInfo(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -377,10 +374,9 @@ class VTFunctionAssociationTableModel extends AddressBasedTableModel<VTFunctionR
|
||||
}
|
||||
monitor.setMessage("Setting filter data...");
|
||||
monitor.initialize(data.size());
|
||||
for (int row = 0; row < data.size(); row++) {
|
||||
for (VTFunctionRowObject rowObject : data) {
|
||||
monitor.checkCanceled();
|
||||
monitor.incrementProgress(1);
|
||||
VTFunctionRowObject rowObject = data.get(row);
|
||||
FunctionAssociationInfo info = rowObject.getInfo();
|
||||
Long functionID = info.getFunctionID();
|
||||
info.setFilterData(matchSet.contains(functionID), acceptedSet.contains(functionID));
|
||||
|
@ -27,7 +27,7 @@ import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class ImpliedMatchAssociationHook implements AssociationHook, VTControllerListener {
|
||||
private VTSession session;
|
||||
@ -66,25 +66,27 @@ public class ImpliedMatchAssociationHook implements AssociationHook, VTControlle
|
||||
if (source == null || destination == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddressCorrelatorManager correlator = controller.getCorrelator();
|
||||
if (autoCreateImpliedMatches) {
|
||||
try {
|
||||
Set<VTImpliedMatchInfo> impliedMatches =
|
||||
ImpliedMatchUtils.findImpliedMatches(controller, source, destination, session,
|
||||
correlator, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
processAssociationAccepted(impliedMatches);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Error auto-creating implied matches for association: " +
|
||||
association);
|
||||
}
|
||||
if (!autoCreateImpliedMatches) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
TaskMonitor monitor = VTTaskMonitor.getTaskMonitor();
|
||||
Set<VTImpliedMatchInfo> impliedMatches = ImpliedMatchUtils.findImpliedMatches(
|
||||
controller, source, destination, session, correlator, monitor);
|
||||
processAssociationAccepted(impliedMatches);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
Msg.info(this, "User cancelled finding implied matches when accepting an assocation");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When a match is accepted either create associated implied matches or if a match already
|
||||
* exists, increase the vote count
|
||||
* @param impliedMatches The implied matches set to either create or increase vote count
|
||||
* @param impliedMatches The implied matches set to either create or increase vote count
|
||||
*/
|
||||
private void processAssociationAccepted(Set<VTImpliedMatchInfo> impliedMatches) {
|
||||
for (VTImpliedMatchInfo impliedMatch : impliedMatches) {
|
||||
@ -112,15 +114,20 @@ public class ImpliedMatchAssociationHook implements AssociationHook, VTControlle
|
||||
if (source == null || destination == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!autoCreateImpliedMatches) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddressCorrelatorManager correlator = controller.getCorrelator();
|
||||
try {
|
||||
Set<VTImpliedMatchInfo> impliedMatches =
|
||||
ImpliedMatchUtils.findImpliedMatches(controller, source, destination, session,
|
||||
correlator, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
TaskMonitor monitor = VTTaskMonitor.getTaskMonitor();
|
||||
Set<VTImpliedMatchInfo> impliedMatches = ImpliedMatchUtils.findImpliedMatches(
|
||||
controller, source, destination, session, correlator, monitor);
|
||||
processAssociationCleared(impliedMatches);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// can't happen - using dummy monitor
|
||||
Msg.info(this, "User cancelled finding implied matches when clearing an assocation");
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,7 +189,7 @@ public class ImpliedMatchAssociationHook implements AssociationHook, VTControlle
|
||||
|
||||
@Override
|
||||
public void sessionUpdated(DomainObjectChangedEvent ev) {
|
||||
// don't care
|
||||
// don't care
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,20 +74,22 @@ public class VTMatchSourceTableModel extends VTMatchOneToManyTableModel {
|
||||
throws CancelledException {
|
||||
List<VTMatchSet> matchSets = session.getMatchSets();
|
||||
VTAssociationManager associationManager = session.getAssociationManager();
|
||||
if (address != null && associationManager != null) {
|
||||
Collection<VTAssociation> associations =
|
||||
associationManager.getRelatedAssociationsBySourceAddress(address);
|
||||
monitor.initialize(associations.size());
|
||||
for (VTAssociation vtAssociation : associations) {
|
||||
if (address == null || associationManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<VTAssociation> associations =
|
||||
associationManager.getRelatedAssociationsBySourceAddress(address);
|
||||
monitor.initialize(associations.size());
|
||||
for (VTAssociation vtAssociation : associations) {
|
||||
monitor.checkCanceled();
|
||||
monitor.incrementProgress(1);
|
||||
for (VTMatchSet matchSet : matchSets) {
|
||||
monitor.checkCanceled();
|
||||
monitor.incrementProgress(1);
|
||||
for (VTMatchSet matchSet : matchSets) {
|
||||
Collection<VTMatch> matches = matchSet.getMatches(vtAssociation);
|
||||
for (VTMatch match : matches) {
|
||||
monitor.checkCanceled();
|
||||
Collection<VTMatch> matches = matchSet.getMatches(vtAssociation);
|
||||
for (VTMatch match : matches) {
|
||||
monitor.checkCanceled();
|
||||
accumulator.add(match);
|
||||
}
|
||||
accumulator.add(match);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,14 +98,14 @@ public class VTMatchSourceTableModel extends VTMatchOneToManyTableModel {
|
||||
@Override
|
||||
protected Comparator<VTMatch> createSortComparator(int columnIndex) {
|
||||
|
||||
//
|
||||
// Unusual Code Alert!: since we define some of our columns for this table model as
|
||||
// off/hidden by default, we cannot rely on the ordinal of the
|
||||
// ColumnDescriptor to match the 'columnIndex' parameter. Instead,
|
||||
//
|
||||
// Unusual Code Alert!: since we define some of our columns for this table model as
|
||||
// off/hidden by default, we cannot rely on the ordinal of the
|
||||
// ColumnDescriptor to match the 'columnIndex' parameter. Instead,
|
||||
// we have to lookup the model's index for the given ColumnDescriptor
|
||||
// and test that value against the index parameter (which is the
|
||||
// and test that value against the index parameter (which is the
|
||||
// value used by the column model.
|
||||
//
|
||||
//
|
||||
|
||||
int destinationAddressColumnIndex = getColumnIndex(DestinationAddressTableColumn.class);
|
||||
if (destinationAddressColumnIndex == columnIndex) {
|
||||
|
@ -64,8 +64,8 @@ public abstract class VtTask extends Task {
|
||||
|
||||
/**
|
||||
* Determine if session events should be suspended during task execution.
|
||||
* This can improve performance during task execution at the expense of bulk
|
||||
* table updates at task completion. Method return false by default.
|
||||
* This can improve performance during task execution at the expense of bulk
|
||||
* table updates at task completion. Method return false by default.
|
||||
* If not constructed with a session this method is not used.
|
||||
* @return true if events should be suspended
|
||||
*/
|
||||
@ -143,7 +143,6 @@ public abstract class VtTask extends Task {
|
||||
|
||||
/**
|
||||
* Returns an HTML formated error message
|
||||
* @param messagePrefix the error message header
|
||||
* @return an HTML formatted error message
|
||||
*/
|
||||
public String getErrorDetails() {
|
||||
|
@ -16,8 +16,7 @@
|
||||
*/
|
||||
package ghidra.feature.vt.gui.util;
|
||||
|
||||
import static ghidra.feature.vt.gui.provider.matchtable.MultipleLabelsRenderer.MultipleLabelsRendererType.DESTINATION;
|
||||
import static ghidra.feature.vt.gui.provider.matchtable.MultipleLabelsRenderer.MultipleLabelsRendererType.SOURCE;
|
||||
import static ghidra.feature.vt.gui.provider.matchtable.MultipleLabelsRenderer.MultipleLabelsRendererType.*;
|
||||
import static ghidra.feature.vt.gui.util.MungedAssocationAndMarkupItemStatus.*;
|
||||
|
||||
import java.awt.Color;
|
||||
@ -102,7 +101,7 @@ public abstract class AbstractVTMatchTableModel extends AddressBasedTableModel<V
|
||||
FilterShortcutState state = filter.getFilterShortcutState();
|
||||
if (state == FilterShortcutState.NEVER_PASSES) {
|
||||
// we have found a filter that will never pass; signal that all filtering will
|
||||
// fail by returning null (the client of this code must know that: null is a
|
||||
// fail by returning null (the client of this code must know that: null is a
|
||||
// special case and that no filtering is required; all items will fail the filter)
|
||||
return null;
|
||||
}
|
||||
@ -212,8 +211,8 @@ public abstract class AbstractVTMatchTableModel extends AddressBasedTableModel<V
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// For now we don't support equals(); if this filter gets re-created,
|
||||
// then the table must be re-filtered. If we decide to implement this method, then
|
||||
// For now we don't support equals(); if this filter gets re-created,
|
||||
// then the table must be re-filtered. If we decide to implement this method, then
|
||||
// we must also implement equals() on the filters used by this filter.
|
||||
return this == obj;
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -47,8 +47,7 @@ import ghidra.util.task.TaskMonitor;
|
||||
public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private static final String TEST_SOURCE_PROGRAM_NAME = "VersionTracking/WallaceSrc";
|
||||
private static final String TEST_DESTINATION_PROGRAM_NAME =
|
||||
"VersionTracking/WallaceVersion2";
|
||||
private static final String TEST_DESTINATION_PROGRAM_NAME = "VersionTracking/WallaceVersion2";
|
||||
|
||||
private VTTestEnv env;
|
||||
private VTController controller;
|
||||
@ -56,10 +55,6 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
private ProgramDB destinationProgram;
|
||||
private VTSessionDB session;
|
||||
|
||||
public VTAutoVersionTrackingTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
@ -93,17 +88,17 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
||||
|
||||
// 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
|
||||
assertCorrectOptionValues(session, "0.999999999", "10.0");
|
||||
|
||||
// verify that given the above verified conditions the
|
||||
// verify that given the above verified conditions the
|
||||
// exact unique correlators (which have their own tests to verify which matches are
|
||||
// correct) return the expected number of possible matches and accepted matches
|
||||
// since they are exact and unique and this number is already known based on other tests
|
||||
// this is just verifying that what we expect to happen is happening for debug purposes
|
||||
// this is just verifying that what we expect to happen is happening for debug purposes
|
||||
// in case something is changed in the future that would alter these numbers.
|
||||
// We need to know that these are as expected before testing the non-exact/unique correlator
|
||||
// results that depend on these answers.
|
||||
// results that depend on these answers.
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session, "Exact Symbol Name Match", 203, 203);
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session, "Exact Data Match", 125, 125);
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session, "Exact Function Bytes Match", 18, 18);
|
||||
@ -135,7 +130,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
|
||||
/*
|
||||
* This tests auto version tracking with the default score/confidence values so some of the
|
||||
* matches are probably not good matches. This was just to make sure that the expected
|
||||
* matches are probably not good matches. This was just to make sure that the expected
|
||||
* results happen in this case and to show difference between this and the more cautious ones.
|
||||
*/
|
||||
@Test
|
||||
@ -149,23 +144,23 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// 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
|
||||
boolean success = runAutoVTCommand(0.5, 1.0);
|
||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
||||
|
||||
// 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
|
||||
assertCorrectOptionValues(session, "0.5", "1.0");
|
||||
|
||||
// verify that given the above verified conditions the
|
||||
// verify that given the above verified conditions the
|
||||
// exact unique correlators (which have their own tests to verify which matches are
|
||||
// correct) return the expected number of possible matches and accepted matches
|
||||
// since they are exact and unique and this number is already known based on other tests
|
||||
// this is just verifying that what we expect to happen is happening for debug purposes
|
||||
// this is just verifying that what we expect to happen is happening for debug purposes
|
||||
// in case something is changed in the future that would alter these numbers.
|
||||
// We need to know that these are as expected before testing the non-exact/unique correlator
|
||||
// results that depend on these answers.
|
||||
// results that depend on these answers.
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session, "Exact Symbol Name Match", 203, 203);
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session, "Exact Data Match", 125, 125);
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session, "Exact Function Bytes Match", 18, 18);
|
||||
@ -208,7 +203,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
VTMatch match = createMatch(addr("0x000411860", sourceProgram),
|
||||
addr("0x00411830", destinationProgram), false);
|
||||
|
||||
//make a second match that conflicts with first match and accept it which will cause the
|
||||
//make a second match that conflicts with first match and accept it which will cause the
|
||||
// first match to be blocked
|
||||
VTMatch match2 = createMatch(addr("0x4117c0", sourceProgram),
|
||||
addr("0x00411830", destinationProgram), true);
|
||||
@ -236,7 +231,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
sourceProgram = env.getProgram(TEST_SOURCE_PROGRAM_NAME);
|
||||
destinationProgram = env.getProgram(TEST_DESTINATION_PROGRAM_NAME);
|
||||
|
||||
// Create three functions in both the source and destination program with matching
|
||||
// Create three functions in both the source and destination program with matching
|
||||
// instructions but different register operands
|
||||
byte[] bytes1 = { (byte) 0x8b, (byte) 0xff, (byte) 0x55, (byte) 0x8b, (byte) 0xec,
|
||||
(byte) 0x33, (byte) 0xc0, (byte) 0x5d, (byte) 0x90, (byte) 0xc3 }; //XOR EAX,EAX;
|
||||
@ -258,10 +253,10 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// run auto VT
|
||||
// run auto VT
|
||||
runAutoVTCommand(1.0, 10.0);
|
||||
|
||||
// Now test that the correct matches were created based on the duplicate functions we created
|
||||
// Now test that the correct matches were created based on the duplicate functions we created
|
||||
String correlator = "Duplicate Function Instructions Match";
|
||||
|
||||
assertAcceptedMatch(session, correlator, "0x414c00", "0x414c00");
|
||||
@ -276,7 +271,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
sourceProgram = env.getProgram(TEST_SOURCE_PROGRAM_NAME);
|
||||
destinationProgram = env.getProgram(TEST_DESTINATION_PROGRAM_NAME);
|
||||
|
||||
// Create three functions in both the source and destination program with matching
|
||||
// Create three functions in both the source and destination program with matching
|
||||
// instructions but different register operands
|
||||
byte[] bytes1 = { (byte) 0x8b, (byte) 0xff, (byte) 0x55, (byte) 0x8b, (byte) 0xec,
|
||||
(byte) 0x33, (byte) 0xc0, (byte) 0x5d, (byte) 0x90, (byte) 0xc3 }; //XOR EAX,EAX;
|
||||
@ -304,10 +299,10 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// run auto VT
|
||||
// run auto VT
|
||||
runAutoVTCommand(1.0, 10.0);
|
||||
|
||||
// Now test that the correct matches were created based on the duplicate functions we created
|
||||
// Now test that the correct matches were created based on the duplicate functions we created
|
||||
String correlator = "Duplicate Function Instructions Match";
|
||||
|
||||
assertAcceptedMatch(session, correlator, "0x414c00", "0x414c00");
|
||||
@ -340,7 +335,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// run auto VT
|
||||
// run auto VT
|
||||
runAutoVTCommand(1.0, 10.0);
|
||||
|
||||
// Test to make sure that they weren't matched by something else first so we can
|
||||
@ -383,7 +378,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
createFunction(sourceProgram, bytes, addr("0x414e00", sourceProgram));
|
||||
createFunction(destinationProgram, bytes, addr("0x414f00", destinationProgram));
|
||||
|
||||
// Create three functions in each program with same instructions as the above functions but
|
||||
// Create three functions in each program with same instructions as the above functions but
|
||||
// replace the XOR EAX, 1 with XOR EAX, 2, XOR EAX, 2, XOR EAX, 3 respectively
|
||||
|
||||
byte[] bytes2 = { (byte) 0x8b, (byte) 0xff, (byte) 0x55, (byte) 0x8b, (byte) 0xec,
|
||||
@ -409,7 +404,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// run auto VT
|
||||
// run auto VT
|
||||
runAutoVTCommand(1.0, 10.0);
|
||||
|
||||
// Test to make sure that they weren't matched by something else first so we can
|
||||
@ -439,11 +434,11 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
}
|
||||
}
|
||||
// 40 = four for the 2x2 matches that already existed and 36 for the 6x6 matches just created
|
||||
// 5 = 2 matches that already existed + 3 valid matches from the ones just created
|
||||
// 5 = 2 matches that already existed + 3 valid matches from the ones just created
|
||||
assertCorrectMatchCountAndAcceptedMatchCount(session,
|
||||
"Duplicate Function Instructions Match", 40, 5);
|
||||
|
||||
// Now test that the Auto VT duplicate matcher did not accept any matches between the three
|
||||
// Now test that the Auto VT duplicate matcher did not accept any matches between the three
|
||||
// identical ones but did accept the unique ones and blocked the ones between the unique ones
|
||||
// and the rest
|
||||
List<Address> identicalSourceAddrs = new ArrayList<>();
|
||||
@ -457,7 +452,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
|
||||
String correlator = "Duplicate Function Instructions Match";
|
||||
|
||||
// Checks that the duplicate identical ones are available matches
|
||||
// Checks that the duplicate identical ones are available matches
|
||||
for (Address sourceAddr : identicalSourceAddrs) {
|
||||
for (Address destAddr : identicalDestAddrs) {
|
||||
assertAvailableMatch(session, correlator, sourceAddr.toString(),
|
||||
@ -516,7 +511,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
sourceProgram = env.getProgram(TEST_SOURCE_PROGRAM_NAME);
|
||||
destinationProgram = env.getProgram(TEST_DESTINATION_PROGRAM_NAME);
|
||||
|
||||
// Create three functions in both the source and destination program with matching
|
||||
// Create three functions in both the source and destination program with matching
|
||||
// instructions but different constant operands and a call with different offset so that
|
||||
// the exact bytes matcher doesn't find it first but it still has the same instructions
|
||||
|
||||
@ -563,7 +558,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// run auto VT
|
||||
// run auto VT
|
||||
runAutoVTCommand(1.0, 10.0);
|
||||
|
||||
// Test to make sure that they weren't matched by something else first so we can
|
||||
@ -585,8 +580,8 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
|
||||
/*
|
||||
* This tests whether the markup from a function gets applied to the destination function
|
||||
* for the case where all instructions line up exactly between both functions. It tests
|
||||
* the apply markup path for unique matches.
|
||||
* for the case where all instructions line up exactly between both functions. It tests
|
||||
* the apply markup path for unique matches.
|
||||
*/
|
||||
@Test
|
||||
public void testMarkup_AllMarkupShouldApply_UniqueMatch() throws Exception {
|
||||
@ -642,8 +637,8 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
|
||||
/*
|
||||
* This tests whether the markup from a function gets applied to the destination function
|
||||
* for the case where all instructions line up exactly between both functions. It tests
|
||||
* the apply markup path for duplicate matches.
|
||||
* for the case where all instructions line up exactly between both functions. It tests
|
||||
* the apply markup path for duplicate matches.
|
||||
*/
|
||||
@Test
|
||||
public void testMarkup_AllMarkupShouldApply_DuplicateMatch() throws Exception {
|
||||
@ -708,13 +703,13 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
|
||||
// Override the setup to switch the source and destination programs.
|
||||
// This is because the destination program has a sample match where the length
|
||||
// of a matching function is greater than the one in the source program and
|
||||
// of a matching function is greater than the one in the source program and
|
||||
// it is needed to test this case.
|
||||
|
||||
sourceProgram = env.getProgram(TEST_DESTINATION_PROGRAM_NAME);
|
||||
destinationProgram = env.getProgram(TEST_SOURCE_PROGRAM_NAME);
|
||||
|
||||
// Now put some markup in the new source function to test such that there is a
|
||||
// Now put some markup in the new source function to test such that there is a
|
||||
// comment at each code unit called Test Comment "n" where n is a one up value starting
|
||||
// at 0
|
||||
Listing sourceListing = sourceProgram.getListing();
|
||||
@ -738,7 +733,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
env.showTool();
|
||||
controller = env.getVTController();
|
||||
|
||||
// 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
|
||||
boolean success = runAutoVTCommand(0.5, 1.0);
|
||||
assertTrue("Auto Version Tracking Command failed to run", success);
|
||||
@ -748,15 +743,16 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
assertAcceptedMatch(session, correlator, "0x4118c0", "0x4118f0");
|
||||
|
||||
// Check that the expected comments were moved over
|
||||
// The case we have is where the source function has a chunk of five code units in the
|
||||
// middle that isn't in the destination function. We need to test that the top set of code
|
||||
// The case we have is where the source function has a chunk of five code units in the
|
||||
// middle that isn't in the destination function. We need to test that the top set of code
|
||||
// units have comments Test Comment 0-n and then skip the five then test the rest that
|
||||
// should match until the end of the function
|
||||
Listing destListing = destinationProgram.getListing();
|
||||
|
||||
// Get the first set of comments that should line up and test them first
|
||||
AddressSet topAddressSet = destinationProgram.getAddressFactory().getAddressSet(
|
||||
addr("0x4118f0", destinationProgram), addr("0x4119ad", destinationProgram));
|
||||
AddressSet topAddressSet = destinationProgram.getAddressFactory()
|
||||
.getAddressSet(addr("0x4118f0", destinationProgram),
|
||||
addr("0x4119ad", destinationProgram));
|
||||
CodeUnitIterator codeUnitsDestTop = destListing.getCodeUnits(topAddressSet, true);
|
||||
|
||||
numComments = 0;
|
||||
@ -771,9 +767,10 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
assertEquals(null,
|
||||
destListing.getComment(CodeUnit.EOL_COMMENT, addr("0x4119af", destinationProgram)));
|
||||
|
||||
// Now get the bottom section
|
||||
AddressSet bottomAddressSet = destinationProgram.getAddressFactory().getAddressSet(
|
||||
addr("0x4119b1", destinationProgram), addr("0x4119e9", destinationProgram));
|
||||
// Now get the bottom section
|
||||
AddressSet bottomAddressSet = destinationProgram.getAddressFactory()
|
||||
.getAddressSet(addr("0x4119b1", destinationProgram),
|
||||
addr("0x4119e9", destinationProgram));
|
||||
CodeUnitIterator codeUnitsDestBottom = destListing.getCodeUnits(bottomAddressSet, true);
|
||||
|
||||
// The five comments from the source should not get moved over so skip those and test that
|
||||
@ -805,10 +802,14 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
info.setConfidenceScore(confidence);
|
||||
VTScore score = new VTScore(1.0);
|
||||
info.setSimilarityScore(score);
|
||||
long sourceLen = sourceProgram.getFunctionManager().getFunctionAt(
|
||||
sourceAddress).getBody().getNumAddresses();
|
||||
long destLen = destinationProgram.getFunctionManager().getFunctionAt(
|
||||
destinationAddress).getBody().getNumAddresses();
|
||||
long sourceLen = sourceProgram.getFunctionManager()
|
||||
.getFunctionAt(sourceAddress)
|
||||
.getBody()
|
||||
.getNumAddresses();
|
||||
long destLen = destinationProgram.getFunctionManager()
|
||||
.getFunctionAt(destinationAddress)
|
||||
.getBody()
|
||||
.getNumAddresses();
|
||||
info.setSourceLength((int) sourceLen);
|
||||
info.setDestinationLength((int) destLen);
|
||||
matchSet.addMatch(info);
|
||||
@ -934,7 +935,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
List<VTMatchSet> matchSets = vtSession.getMatchSets();
|
||||
|
||||
for (VTMatchSet matchSet : matchSets) {
|
||||
// Ignore the matchSet with the given correlator name
|
||||
// Ignore the matchSet with the given correlator name
|
||||
if (matchSet.getProgramCorrelatorInfo().getName().equals(correlatorName)) {
|
||||
continue;
|
||||
}
|
||||
@ -994,7 +995,7 @@ public class VTAutoVersionTrackingTest extends AbstractGhidraHeadedIntegrationTe
|
||||
assertBlockedMatch(vtSession, correlator, "0x412330", "0x4122e0");
|
||||
}
|
||||
|
||||
// These are the matches when score is .999999999 and log 10 conf threshold is 2.0
|
||||
// These are the matches when score is .999999999 and log 10 conf threshold is 2.0
|
||||
private void assertCombinedReferenceMatchStatusesHigherScoreAndConfidence(VTSession vtSession) {
|
||||
|
||||
String correlator = "Combined Function and Data Reference Match";
|
||||
|
@ -108,11 +108,19 @@ public abstract class Task implements MonitoredRunnable {
|
||||
return SwingConstants.CENTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the 'wait for completed task' boolean that was passed into this class
|
||||
* @return the value
|
||||
*/
|
||||
public boolean getWaitForTaskCompleted() {
|
||||
return waitForTaskCompleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* When an object implementing interface <code>Runnable</code> is used to create a thread,
|
||||
* starting the thread causes the object's <code>run</code> method to be called in that
|
||||
* separately executing thread.
|
||||
*
|
||||
*
|
||||
* @param monitor the task monitor
|
||||
*/
|
||||
@Override
|
||||
@ -176,13 +184,13 @@ public abstract class Task implements MonitoredRunnable {
|
||||
|
||||
/**
|
||||
* This is the method that will be called to do the work
|
||||
*
|
||||
*
|
||||
* <P>Note: The run(TaskMonitor) method should not make any calls directly
|
||||
* on Swing components, as these calls are not thread safe. Place Swing
|
||||
* calls in a Runnable, then call {@link Swing#runLater(Runnable)} or
|
||||
* {@link Swing#runNow(Runnable)}to schedule the Runnable inside of
|
||||
* the AWT Event Thread.
|
||||
*
|
||||
*
|
||||
* @param monitor The TaskMonitor that will monitor the executing Task
|
||||
* @throws CancelledException if the task is cancelled. Subclasses can trigger this exception
|
||||
* by calling {@link TaskMonitor#checkCanceled()}. This allows
|
||||
|
Loading…
Reference in New Issue
Block a user