Fixed tests failing to recent Version Tracking updates. Added a

priority to Version Tracking address correlators.
This commit is contained in:
dragonmacher 2024-07-23 18:01:38 -04:00
parent 220d6d9f58
commit 0fbd23653d
24 changed files with 488 additions and 293 deletions

View file

@ -44,7 +44,6 @@ public class AnalysisPriority {
*
*/
/**
* Defines a full format analysis as the first priority for automatic analysis.
* These are the first analyzers that will run after import.
@ -78,7 +77,7 @@ public class AnalysisPriority {
* instructions <code>AnalyzerType.INSTRUCTIONS</code>. It is also useful for
* those analyzers that depend on code, but want to analyze flow, such as non-returning
* functions, that should happen before functions are widely laid down. If
* bad flow is not fixed at an early priority, switch stmt recovery, function
* bad flow is not fixed at an early priority, switch statement recovery, function
* boundaries, etc... may need to be redone and bad stuff cleaned up.
*/
public final static AnalysisPriority CODE_ANALYSIS = DISASSEMBLY.getNext("CODE");
@ -114,8 +113,8 @@ public class AnalysisPriority {
DATA_ANALYSIS.getNext("FUNCTION ID");
/**
* Defines data type propogation as the ninth priority for automatic analysis.
* Data type propogation analysis should hapen as late as possible so that all basic code
* Defines data type propagation as the ninth priority for automatic analysis.
* Data type propagation analysis should happen as late as possible so that all basic code
* recovery, reference analysis, etc... has taken place.
*/
public final static AnalysisPriority DATA_TYPE_PROPOGATION =
@ -136,6 +135,7 @@ public class AnalysisPriority {
/**
* Construct a new priority object.
* @param name the name
* @param priority priority to use
*/
public AnalysisPriority(String name, int priority) {
@ -145,6 +145,7 @@ public class AnalysisPriority {
/**
* Return the priority specified for this analysis priority.
* @return the priority specified for this analysis priority.
*/
public int priority() {
return priority;
@ -160,7 +161,7 @@ public class AnalysisPriority {
}
/**
* Get a piority that is a little lower than this one.
* Get a priority that is a little lower than this one.
*
* @return a lower priority
*/
@ -170,6 +171,7 @@ public class AnalysisPriority {
/**
* Return first gross priority.
* @param name the name
* @return first gross priority
*/
public static AnalysisPriority getInitial(String name) {
@ -178,6 +180,7 @@ public class AnalysisPriority {
/**
* Get the next gross priority.
* @param nextName the next name
* @return return next gross priority
*/
public AnalysisPriority getNext(String nextName) {

View file

@ -31,6 +31,9 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class CodeCompareAddressCorrelation implements AddressCorrelation {
public static final String NAME = "CodeCompareAddressCorrelator";
static enum CorrelationKind {
CODE_COMPARE, LCS, PARAMETERS;
}
@ -65,15 +68,16 @@ public class CodeCompareAddressCorrelation implements AddressCorrelation {
}
@Override
public AddressRange getCorrelatedDestinationRange(Address sourceAddress, TaskMonitor monitor)
throws CancelledException {
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
TaskMonitor monitor) throws CancelledException {
initialize(monitor);
CorrelationContainer container = cachedForwardAddressMap.get(sourceAddress);
if (container == null) {
return null;
}
return container.range;
return new AddressCorrelationRange(container.range, getName());
}
private static final Comparator<CodeUnit> CUCOMPARATOR = new Comparator<CodeUnit>() {
@ -446,6 +450,6 @@ public class CodeCompareAddressCorrelation implements AddressCorrelation {
@Override
public String getName() {
return "CodeCompareAddressCorrelator";
return NAME;
}
}

View file

@ -20,9 +20,9 @@ import ghidra.framework.options.ToolOptions;
import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.*;
import ghidra.program.util.AddressCorrelation;
import ghidra.program.util.DiscoverableAddressCorrelator;
import ghidra.program.util.AddressCorrelator;
public class CodeCompareAddressCorrelator implements DiscoverableAddressCorrelator {
public class CodeCompareAddressCorrelator implements AddressCorrelator {
private static final String OPTIONS_NAME = "CodeCompareAddressCorrelator";
@ -40,7 +40,9 @@ public class CodeCompareAddressCorrelator implements DiscoverableAddressCorrelat
Language l1 = p1.getLanguage();
Language l2 = p2.getLanguage();
if (l1.getLanguageID().equals(l2.getLanguageID())) {
return null; // this correlator is best used with different architectures
// this correlator is best used with different architectures, assuming we have simpler
// and faster correlators that should be run with the same language
return null;
}
return new CodeCompareAddressCorrelation(sourceFunction, destinationFunction);
@ -65,4 +67,11 @@ public class CodeCompareAddressCorrelator implements DiscoverableAddressCorrelat
public Options getDefaultOptions() {
return new ToolOptions(OPTIONS_NAME);
}
@Override
public int getPriority() {
// Run just above the last chance priority, which allows this correlator to be the fallback,
// general purpose correlator.
return LATE_CHANCE_PRIORITY - PRIORITY_OFFSET;
}
}

View file

@ -28,6 +28,8 @@ dependencies {
api project(":Base")
runtimeOnly project(":CodeCompare")
testImplementation project(path: ':CodeCompare', configuration: 'testArtifacts')
testImplementation project(path: ':Project', configuration: 'testArtifacts')
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
}

View file

@ -25,20 +25,13 @@ import ghidra.program.util.*;
* This is the correlator of last resort. It is the last correlator to be checked when trying to
* acquire a correlation.
*/
public class LastResortAddressCorrelator implements AddressCorrelator {
public class LinearAddressCorrelator implements AddressCorrelator {
private static final String CORRELATOR_NAME = "LastResortAddressCorrelator";
private ToolOptions options = new ToolOptions(CORRELATOR_NAME);
public LastResortAddressCorrelator() {
}
@Override
public AddressCorrelation correlate(Function sourceFunction, Function destinationFunction) {
if (sourceFunction.getProgram().getLanguage().getLanguageDescription().getProcessor().equals(
destinationFunction.getProgram().getLanguage().getLanguageDescription().getProcessor())) {
return new VTHashedFunctionAddressCorrelation(sourceFunction, destinationFunction);
}
return new LinearFunctionAddressCorrelation(sourceFunction, destinationFunction);
}
@ -61,4 +54,9 @@ public class LastResortAddressCorrelator implements AddressCorrelator {
public Options getDefaultOptions() {
return new ToolOptions(CORRELATOR_NAME);
}
@Override
public int getPriority() {
return LATE_CHANCE_PRIORITY;
}
}

View file

@ -21,6 +21,7 @@ import java.util.Map;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.program.util.AddressCorrelation;
import ghidra.program.util.AddressCorrelationRange;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -52,25 +53,33 @@ public class StraightLineCorrelation implements AddressCorrelation {
}
@Override
public AddressRange getCorrelatedDestinationRange(Address sourceAddress, TaskMonitor monitor)
throws CancelledException {
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
TaskMonitor monitor) throws CancelledException {
initialize(monitor);
return cachedForwardAddressMap.get(sourceAddress);
AddressRange range = cachedForwardAddressMap.get(sourceAddress);
return new AddressCorrelationRange(range, getName());
}
private void initialize(TaskMonitor monitor) throws CancelledException {
if (cachedForwardAddressMap != null) return;
if (cachedForwardAddressMap != null) {
return;
}
cachedForwardAddressMap = new HashMap<Address, AddressRange>();
AddressSetView sourceAddressSet = (sourceFunction != null) ? sourceFunction.getBody() : null;
AddressSetView destinationAddressSet = (destinationFunction != null) ? destinationFunction.getBody() : null;
AddressSetView sourceAddressSet =
(sourceFunction != null) ? sourceFunction.getBody() : null;
AddressSetView destinationAddressSet =
(destinationFunction != null) ? destinationFunction.getBody() : null;
if (sourceAddressSet == null || destinationAddressSet == null)
if (sourceAddressSet == null || destinationAddressSet == null) {
return;
}
CodeUnitIterator srcIter = sourceFunction.getProgram().getListing().getCodeUnits(sourceAddressSet, true);
CodeUnitIterator destIter = destinationFunction.getProgram().getListing().getCodeUnits(destinationAddressSet, true);
CodeUnitIterator srcIter =
sourceFunction.getProgram().getListing().getCodeUnits(sourceAddressSet, true);
CodeUnitIterator destIter =
destinationFunction.getProgram().getListing().getCodeUnits(destinationAddressSet, true);
monitor.setMessage("Defining address ranges...");
monitor.initialize(sourceAddressSet.getNumAddresses());
@ -84,9 +93,10 @@ public class StraightLineCorrelation implements AddressCorrelation {
monitor.incrementProgress(srcCodeUnit.getLength());
defineRange(cachedForwardAddressMap, srcCodeUnit, destCodeUnit);
}
else
else {
break; // First mismatch we break out of the loop
}
}
computeParamCorrelation();
}
@ -124,12 +134,11 @@ public class StraightLineCorrelation implements AddressCorrelation {
* @param sourceCodeUnit is the source code unit
* @param destinationCodeUnit is the matching destination code unit
*/
private static void defineRange(Map<Address, AddressRange> map,
CodeUnit sourceCodeUnit, CodeUnit destinationCodeUnit) {
private static void defineRange(Map<Address, AddressRange> map, CodeUnit sourceCodeUnit,
CodeUnit destinationCodeUnit) {
Address minAddress = sourceCodeUnit.getMinAddress();
Address maxAddress = sourceCodeUnit.getMaxAddress();
AddressRangeImpl toRange =
new AddressRangeImpl(destinationCodeUnit.getMinAddress(),
AddressRangeImpl toRange = new AddressRangeImpl(destinationCodeUnit.getMinAddress(),
destinationCodeUnit.getMaxAddress());
while (!minAddress.equals(maxAddress)) {
map.put(minAddress, toRange);

View file

@ -17,7 +17,8 @@ package ghidra.feature.vt.api.correlator.address;
import static ghidra.util.datastruct.Duo.Side.*;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRangeImpl;
import ghidra.program.model.correlate.HashedFunctionAddressCorrelation;
import ghidra.program.model.listing.Function;
import ghidra.program.model.mem.MemoryAccessException;
@ -57,15 +58,16 @@ public class VTHashedFunctionAddressCorrelation implements AddressCorrelation {
}
@Override
public AddressRange getCorrelatedDestinationRange(Address sourceAddress, TaskMonitor monitor)
throws CancelledException {
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
TaskMonitor monitor) throws CancelledException {
try {
initializeCorrelation(monitor);
Address destinationAddress = addressCorrelation.getAddress(RIGHT, sourceAddress);
if (destinationAddress == null) {
return null; // No matching destination.
}
return new AddressRangeImpl(destinationAddress, destinationAddress);
AddressRangeImpl range = new AddressRangeImpl(destinationAddress, destinationAddress);
return new AddressCorrelationRange(range, getName());
}
catch (MemoryAccessException e) {
Msg.error(this, "Could not create HashedFunctionAddressCorrelation", e);
@ -81,15 +83,14 @@ public class VTHashedFunctionAddressCorrelation implements AddressCorrelation {
* @throws CancelledException if the user cancels
* @throws MemoryAccessException if either function's memory can't be accessed.
*/
private void initializeCorrelation(TaskMonitor monitor) throws CancelledException,
MemoryAccessException {
private void initializeCorrelation(TaskMonitor monitor)
throws CancelledException, MemoryAccessException {
if (addressCorrelation != null) {
return;
}
if (sourceFunction != null && destinationFunction != null) {
addressCorrelation =
new HashedFunctionAddressCorrelation(sourceFunction, destinationFunction,
monitor);
new HashedFunctionAddressCorrelation(sourceFunction, destinationFunction, monitor);
}
else {
addressCorrelation = new DummyListingAddressCorrelation();

View file

@ -0,0 +1,72 @@
/* ###
* 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.api.correlator.address;
import ghidra.framework.options.Options;
import ghidra.framework.options.ToolOptions;
import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Function;
import ghidra.program.util.AddressCorrelation;
import ghidra.program.util.AddressCorrelator;
/**
* An address correlator that may use the {@link VTHashedFunctionAddressCorrelation}.
*/
public class VTHashedFunctionAddressCorrelator implements AddressCorrelator {
public static final String NAME = "VTHashedFunctionAddressCorrelator";
private ToolOptions options = new ToolOptions(NAME);
@Override
public AddressCorrelation correlate(Function sourceFunction, Function destinationFunction) {
Language sourceLanguage = sourceFunction.getProgram().getLanguage();
Language destinationLanguage = destinationFunction.getProgram().getLanguage();
if (sourceLanguage.getProcessor().equals(destinationLanguage.getProcessor())) {
return new VTHashedFunctionAddressCorrelation(sourceFunction, destinationFunction);
}
return null;
}
@Override
public AddressCorrelation correlate(Data sourceData, Data destinationData) {
return null;
}
@Override
public ToolOptions getOptions() {
return options;
}
@Override
public void setOptions(ToolOptions options) {
this.options = options.copy();
}
@Override
public Options getDefaultOptions() {
return new ToolOptions(NAME);
}
@Override
public int getPriority() {
// Run just above default / discovered correlators. Correlator authors can change their
// priority to take precedence over this correlator.
return DEFAULT_PRIORITY - PRIORITY_OFFSET;
}
}

View file

@ -44,6 +44,7 @@ public interface VTMarkupItem {
* address and the address source must be set prior to calling this method.
*
* @param applyAction the type of apply action to take when applying the given markup item
* @param options the options
* @throws VersionTrackingApplyException if an error occurred while attempting to apply the
* markup item.
*/
@ -94,7 +95,7 @@ public interface VTMarkupItem {
* Returns the editable status of this markup item's destination address.
*
* @return the editable status of this markup item's destination address.
* @see #setDestinationAddress(Address, String)
* @see #setDestinationAddress(Address)
*/
public VTMarkupItemDestinationAddressEditStatus getDestinationAddressEditStatus();
@ -110,7 +111,6 @@ public interface VTMarkupItem {
*
* @param status The <b>considered</b> status to set
* @throws IllegalStateException if you call this method on an applied item
* @see #setUnconsidered()
*/
public void setConsidered(VTMarkupItemConsideredStatus status);
@ -124,6 +124,7 @@ public interface VTMarkupItem {
* Returns an optional description of the current markup item status. For example, if there
* status is {@link VTMarkupItemStatus#FAILED_APPLY}, then this method should return a
* description of the failure.
* @return the description.
*/
public String getStatusDescription();

View file

@ -15,9 +15,12 @@
*/
package ghidra.feature.vt.api.markuptype;
import java.util.List;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.gui.util.*;
import ghidra.feature.vt.gui.util.VTMatchApplyChoices;
import ghidra.feature.vt.gui.util.VTMatchApplyChoices.CommentChoices;
import ghidra.feature.vt.gui.util.VTOptionDefines;
import ghidra.framework.options.Options;
import ghidra.framework.options.ToolOptions;
import ghidra.program.model.address.Address;
@ -26,8 +29,6 @@ import ghidra.program.model.listing.Program;
import ghidra.program.util.PlateFieldLocation;
import ghidra.program.util.ProgramLocation;
import java.util.List;
public class PlateCommentMarkupType extends CommentMarkupType {
//==================================================================================================
@ -102,14 +103,16 @@ public class PlateCommentMarkupType extends CommentMarkupType {
options.setEnum(VTOptionDefines.PLATE_COMMENT, CommentChoices.APPEND_TO_EXISTING);
break;
case ADD_AS_PRIMARY:
throw new IllegalArgumentException(getDisplayName() +
" markup items cannot perform an Add As Primary action.");
throw new IllegalArgumentException(
getDisplayName() + " markup items cannot perform an Add As Primary action.");
case REPLACE_DEFAULT_ONLY:
throw new IllegalArgumentException(getDisplayName() +
" markup items cannot perform a Replace Default Only action.");
case REPLACE:
options.setEnum(VTOptionDefines.PLATE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
break;
default:
break;
}
return options;
}

View file

@ -22,7 +22,8 @@ import org.jdom.Element;
import generic.cache.FixedSizeMRUCachingFactory;
import generic.stl.Pair;
import ghidra.feature.vt.api.correlator.address.ExactMatchAddressCorrelator;
import ghidra.feature.vt.api.correlator.address.LastResortAddressCorrelator;
import ghidra.feature.vt.api.correlator.address.VTHashedFunctionAddressCorrelator;
import ghidra.features.codecompare.correlator.CodeCompareAddressCorrelator;
import ghidra.framework.options.*;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Function;
@ -37,6 +38,20 @@ public class AddressCorrelatorManager {
private static final int DATA_CORRELATION_CACHE_SIZE = 5;
private static final int FUNCTION_CORRELATION_CACHE_SIZE = 5;
private static final Comparator<? super AddressCorrelator> CORRELATOR_COMPARATOR = (c1, c2) -> {
int p1 = c1.getPriority();
int p2 = c2.getPriority();
int d = p1 - p2;
if (d != 0) {
return d;
}
// pick something as a tie-breaker
String n1 = c1.getClass().getSimpleName();
String n2 = c2.getClass().getSimpleName();
return n1.compareTo(n2);
};
private List<AddressCorrelator> correlatorList;
@ -55,22 +70,25 @@ public class AddressCorrelatorManager {
private void initializeAddressCorrelators(VTSessionSupplier sessionSupplier) {
correlatorList.add(new ExactMatchAddressCorrelator(sessionSupplier));
correlatorList.add(new VTHashedFunctionAddressCorrelator());
correlatorList.add(new CodeCompareAddressCorrelator());
// Note: at the time of writing this comment, the linear address correlator will not be
// executed. The VTHashedFunctionAddressCorrelator handles correlation between programs
// with the same architecture and the CodeCompareAddressCorrelator handles correlation
// between programs with different architectures.
// correlatorList.add(new LinearAddressCorrelator());
correlatorList.addAll(initializeAddressCorrelators());
correlatorList.sort(CORRELATOR_COMPARATOR);
}
private List<AddressCorrelator> initializeAddressCorrelators() {
List<DiscoverableAddressCorrelator> instances =
ClassSearcher.getInstances(DiscoverableAddressCorrelator.class);
List<AddressCorrelator> addressCorrelatorList = new ArrayList<AddressCorrelator>(instances);
Collections.sort(addressCorrelatorList,
(o1, o2) -> o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName()));
// Put the LastResortCorrelator in case a better address correlation isn't found.
addressCorrelatorList.add(new LastResortAddressCorrelator());
return addressCorrelatorList;
return new ArrayList<AddressCorrelator>(instances);
}
public AddressCorrelation getCorrelator(Function source, Function destination) {
@ -82,6 +100,7 @@ public class AddressCorrelatorManager {
}
private AddressCorrelation getFunctionCorrelator(Function source, Function destination) {
for (AddressCorrelator correlator : correlatorList) {
AddressCorrelation correlation = correlator.correlate(source, destination);
if (correlation != null) {
@ -92,12 +111,14 @@ public class AddressCorrelatorManager {
}
private AddressCorrelation getDataCorrelator(Data source, Data destination) {
for (AddressCorrelator correlator : correlatorList) {
AddressCorrelation correlation = correlator.correlate(source, destination);
if (correlation != null) {
return correlation;
}
}
return null;
}

View file

@ -1153,14 +1153,19 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
@Override
public boolean isSubFilterOf(Filter<VTMatch> otherFilter) {
if (columnFilter == null) {
return false;
Class<?> clazz = getClass();
Class<?> otherClazz = otherFilter.getClass();
if (!clazz.equals(otherClazz)) {
return false; // must be the same class
}
VTColumnFilter otherColumnFilter = (VTColumnFilter) otherFilter;
if (columnFilter == null && otherColumnFilter.columnFilter == null) {
return true;
}
if (otherFilter instanceof VTColumnFilter otherColumnFilter) {
return columnFilter.isSubFilterOf(otherColumnFilter.columnFilter);
}
return false;
}
}

View file

@ -25,10 +25,10 @@ import ghidra.feature.vt.api.util.VersionTrackingApplyException;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.util.MatchInfo;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Function;
import ghidra.program.util.AddressCorrelation;
import ghidra.program.util.AddressCorrelationRange;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -133,13 +133,16 @@ public class ClearMatchTask extends VtTask {
return;
}
Address destinationAddress = null;
AddressRange range =
AddressCorrelationRange range =
correlation.getCorrelatedDestinationRange(markupItem.getSourceAddress(), monitor);
Address destinationAddress = null;
String source = null;
if (range != null) {
destinationAddress = range.getMinAddress();
source = range.getCorrelatorName();
}
markupItem.setDefaultDestinationAddress(destinationAddress, correlation.getName());
markupItem.setDefaultDestinationAddress(destinationAddress, source);
}
private void clearMatch(VTMatch match) {

View file

@ -21,8 +21,8 @@ import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.api.util.VersionTrackingApplyException;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.util.AddressCorrelation;
import ghidra.program.util.AddressCorrelationRange;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -90,11 +90,11 @@ public class UnapplyMarkupItemTask extends VtTask {
Address destinationAddress = null;
String source = null;
if (correlation != null) {
AddressRange range =
AddressCorrelationRange range =
correlation.getCorrelatedDestinationRange(markupItem.getSourceAddress(), monitor);
if (range != null) {
destinationAddress = range.getMinAddress();
source = correlation.getName();
source = range.getCorrelatorName();
}
}

View file

@ -27,6 +27,7 @@ import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.program.util.AddressCorrelation;
import ghidra.program.util.AddressCorrelationRange;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -191,7 +192,8 @@ public class ImpliedMatchUtils {
Address srcRefFromAddress = sourceRef.getFromAddress();
// Get the destination reference address corresponding to the given source reference address
AddressRange range = correlator.getCorrelatedDestinationRange(srcRefFromAddress, monitor);
AddressCorrelationRange range =
correlator.getCorrelatedDestinationRange(srcRefFromAddress, monitor);
if (range == null) {
return null;
}

View file

@ -147,8 +147,8 @@ public class MatchInfo {
return markupItemsCache.get(monitor);
}
private void setDefaultDestination(VTMarkupItem markupItem,
AddressCorrelation addressTranslator, TaskMonitor monitor) throws CancelledException {
private void setDefaultDestination(VTMarkupItem markupItem, AddressCorrelation correlation,
TaskMonitor monitor) throws CancelledException {
Address destinationAddress = getDestinationAddress(markupItem);
Address sourceAddress = markupItem.getSourceAddress();
@ -158,12 +158,12 @@ public class MatchInfo {
}
String destinationAddressSource = null;
if (addressTranslator != null) {
AddressRange correlatedDestinationRange =
addressTranslator.getCorrelatedDestinationRange(sourceAddress, monitor);
if (correlatedDestinationRange != null) {
destinationAddress = correlatedDestinationRange.getMinAddress();
destinationAddressSource = addressTranslator.getName();
if (correlation != null) {
AddressCorrelationRange range =
correlation.getCorrelatedDestinationRange(sourceAddress, monitor);
if (range != null) {
destinationAddress = range.getMinAddress();
destinationAddressSource = range.getCorrelatorName();
}
}
@ -204,22 +204,23 @@ public class MatchInfo {
return null;
}
AddressCorrelation addressTranslator = getAddressTranslator(correlatorMgr);
if (addressTranslator == null) {
AddressCorrelation correlation = getAddressTranslator(correlatorMgr);
if (correlation == null) {
return null;
}
AddressRange correlatedDestinationRange = null;
AddressCorrelationRange range = null;
try {
correlatedDestinationRange =
addressTranslator.getCorrelatedDestinationRange(sourceAddress, TaskMonitor.DUMMY);
range = correlation.getCorrelatedDestinationRange(sourceAddress, TaskMonitor.DUMMY);
}
catch (CancelledException e) {
// check for null below
}
if (correlatedDestinationRange == null) {
if (range == null) {
return null;
}
return correlatedDestinationRange.getMinAddress();
return range.getMinAddress();
}
public VTMarkupItem getCurrentMarkupForLocation(ProgramLocation programLocation,

View file

@ -17,7 +17,7 @@ package ghidra.feature.vt.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import ghidra.feature.vt.api.correlator.address.LastResortAddressCorrelator;
import ghidra.feature.vt.api.correlator.address.LinearAddressCorrelator;
import ghidra.feature.vt.gui.plugin.*;
import ghidra.framework.options.Options;
import ghidra.framework.options.SaveState;
@ -61,7 +61,7 @@ public class VTControllerTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull("The controller did not find any correlators", correlator);
// set some options settings
Options options = correlator.getOptions(LastResortAddressCorrelator.class);
Options options = correlator.getOptions(LinearAddressCorrelator.class);
String testDefaultValue = "Test Default Value";
String testOptionKey = "Test Option Name";
String value = options.getString(testOptionKey, testDefaultValue);
@ -70,7 +70,7 @@ public class VTControllerTest extends AbstractGhidraHeadedIntegrationTest {
String firstNewOptionValue = "New Option Value";
options.setString(testOptionKey, firstNewOptionValue);
assertEquals(firstNewOptionValue, options.getString(testOptionKey, null));
correlator.setOptions(LastResortAddressCorrelator.class, options);
correlator.setOptions(LinearAddressCorrelator.class, options);
// save the options
SaveState saveState = new SaveState();
controller.writeConfigState(saveState);
@ -78,12 +78,12 @@ public class VTControllerTest extends AbstractGhidraHeadedIntegrationTest {
// change the options
String secondNewValue = "Second New Value";
options.setString(testOptionKey, secondNewValue);
correlator.setOptions(LastResortAddressCorrelator.class, options);
correlator.setOptions(LinearAddressCorrelator.class, options);
// pull the values again and make sure they are still correct (that writing the config
// state did not change the cached controller and options)
correlator = controller.getCorrelator();
options = correlator.getOptions(LastResortAddressCorrelator.class);
options = correlator.getOptions(LinearAddressCorrelator.class);
assertEquals(secondNewValue, options.getString(testOptionKey, null));
// restore the options
@ -93,7 +93,7 @@ public class VTControllerTest extends AbstractGhidraHeadedIntegrationTest {
// (we have to pull the correlator and options again, as changing the config state may
// change the cached values in the controller)
correlator = controller.getCorrelator();
options = correlator.getOptions(LastResortAddressCorrelator.class);
options = correlator.getOptions(LinearAddressCorrelator.class);
assertEquals(firstNewOptionValue, options.getString(testOptionKey, null));
}
}

View file

@ -30,14 +30,12 @@ import ghidra.feature.vt.api.markuptype.*;
import ghidra.feature.vt.api.util.Stringable;
import ghidra.feature.vt.gui.VTTestEnv;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.features.codecompare.correlator.CodeCompareAddressCorrelation;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.util.AddressCorrelation;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
@ -91,12 +89,13 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
createSession(TEST_SOURCE_PROGRAM_NAME, TEST_DESTINATION_PROGRAM_NAME);
vtTestEnv.showTool();
addComment(CodeUnit.EOL_COMMENT, "0x0041222b", "Exact bytes comment.");
addProgramCorrelation(new ExactMatchBytesProgramCorrelatorFactory());
useMatch("0x00412210", "0x004121f0");
checkAddressCorrelation(StraightLineCorrelation.NAME);
checkCommentMarkup(EolCommentMarkupType.INSTANCE, "0x0041222b", "Exact bytes comment.",
"0x0041220b");
checkMarkupDestinationSource(StraightLineCorrelation.NAME, false);
runCorrelator(new ExactMatchBytesProgramCorrelatorFactory());
selectMatch("0x00412210", "0x004121f0");
validateCommentMarkupItems(EolCommentMarkupType.INSTANCE, "0x0041222b",
"Exact bytes comment.", "0x0041220b");
validateMarkupDestinationAddress(StraightLineCorrelation.NAME, false);
}
@Test
@ -105,12 +104,13 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
createSession(TEST_SOURCE_PROGRAM_NAME, TEST_DESTINATION_PROGRAM_NAME);
vtTestEnv.showTool();
addComment(CodeUnit.PRE_COMMENT, "0x00412988", "Exact mnemonics comment.");
addProgramCorrelation(new ExactMatchMnemonicsProgramCorrelatorFactory());
useMatch("0x00412950", "0x00412930");
checkAddressCorrelation(StraightLineCorrelation.NAME);
checkCommentMarkup(PreCommentMarkupType.INSTANCE, "0x00412988", "Exact mnemonics comment.",
"0x00412968");
checkMarkupDestinationSource(StraightLineCorrelation.NAME, false);
runCorrelator(new ExactMatchMnemonicsProgramCorrelatorFactory());
selectMatch("0x00412950", "0x00412930");
validateCommentMarkupItems(PreCommentMarkupType.INSTANCE, "0x00412988",
"Exact mnemonics comment.", "0x00412968");
validateMarkupDestinationAddress(StraightLineCorrelation.NAME, false);
}
@Test
@ -119,12 +119,13 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
createSession(TEST_SOURCE_PROGRAM_NAME, TEST_DESTINATION_PROGRAM_NAME);
vtTestEnv.showTool();
addComment(CodeUnit.POST_COMMENT, "0x004129a2", "Exact instructions comment.");
addProgramCorrelation(new ExactMatchInstructionsProgramCorrelatorFactory());
useMatch("0x00412950", "0x00412930");
checkAddressCorrelation(StraightLineCorrelation.NAME);
checkCommentMarkup(PostCommentMarkupType.INSTANCE, "0x004129a2",
runCorrelator(new ExactMatchInstructionsProgramCorrelatorFactory());
selectMatch("0x00412950", "0x00412930");
validateCommentMarkupItems(PostCommentMarkupType.INSTANCE, "0x004129a2",
"Exact instructions comment.", "0x00412982");
checkMarkupDestinationSource(StraightLineCorrelation.NAME, false);
validateMarkupDestinationAddress(StraightLineCorrelation.NAME, false);
}
@Test
@ -135,14 +136,15 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
vtTestEnv.showTool();
addComment(CodeUnit.EOL_COMMENT, "0x004126dd", "Similar name eol comment.");
addComment(CodeUnit.PRE_COMMENT, "0x004126d7", "Similar name pre comment.");
addProgramCorrelation(new SimilarSymbolNameProgramCorrelatorFactory());
useMatch("0x00412690", "0x00412720");
checkAddressCorrelation(VTHashedFunctionAddressCorrelation.NAME);
checkCommentMarkup(EolCommentMarkupType.INSTANCE, "0x004126dd", "Similar name eol comment.",
"0x0041277f");
checkCommentMarkup(PreCommentMarkupType.INSTANCE, "0x004126d7", "Similar name pre comment.",
"NO_ADDRESS");
checkMarkupDestinationSource(VTHashedFunctionAddressCorrelation.NAME, true);
runCorrelator(new SimilarSymbolNameProgramCorrelatorFactory());
selectMatch("0x00412690", "0x00412720");
validateCommentMarkupItems(EolCommentMarkupType.INSTANCE, "0x004126dd",
"Similar name eol comment.", "0x0041277f");
validateCommentMarkupItems(PreCommentMarkupType.INSTANCE, "0x004126d7",
"Similar name pre comment.", "NO_ADDRESS");
validateMarkupDestinationAddress(VTHashedFunctionAddressCorrelation.NAME, true);
}
@Test
@ -154,15 +156,26 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
createSession(languageProgram1, languageProgram2);
vtTestEnv.showTool();
// add source comment
addComment(CodeUnit.PLATE_COMMENT, "0x00401003",
"Similar name plate comment not at entry.");
addProgramCorrelation(new SimilarSymbolNameProgramCorrelatorFactory());
useMatch("0x00401000", "0x00402000");
checkAddressCorrelation(LinearFunctionAddressCorrelation.NAME);
// Check for our linear function correlation even though destination will be offcut.
checkCommentMarkup(PlateCommentMarkupType.INSTANCE, "0x00401003",
"Similar name plate comment not at entry.", "0x00402003");
checkMarkupDestinationSource(LinearFunctionAddressCorrelation.NAME, false);
// create correlation run
runCorrelator(new SimilarSymbolNameProgramCorrelatorFactory());
// accept a match
selectMatch("0x00401000", "0x00402000");
// Verify the entry point plate comment markup has a destination address.
validateCommentMarkupItems(PlateCommentMarkupType.INSTANCE, "0x00401000",
"First plate comment.", "0x00402000");
// The non-entry point plate comment markup has no address found when using the
// Code Compare correlators
validateCommentMarkupItems(PlateCommentMarkupType.INSTANCE, "0x00401003",
"Similar name plate comment not at entry.", "NO_ADDRESS");
validateMarkupDestinationAddress(CodeCompareAddressCorrelation.NAME, true);
}
@Test
@ -170,18 +183,18 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
// Test a function match created by the Similar Symbol Name correlator where the
// two programs are for different languages but the same processor with different
// instructions.
Program languageProgram1 = buildProgram1("language1");
Program languageProgram2 = buildProgram3("language3");
createSession(languageProgram1, languageProgram2);
Program p1 = buildProgram1("language1");
Program p2 = buildProgram3("language3");
createSession(p1, p2);
vtTestEnv.showTool();
addComment(CodeUnit.EOL_COMMENT, "0x00401003", "Similar name eol comment.");
addProgramCorrelation(new SimilarSymbolNameProgramCorrelatorFactory());
useMatch("0x00401000", "0x00402000");
checkAddressCorrelation(VTHashedFunctionAddressCorrelation.NAME);
checkCommentMarkup(EolCommentMarkupType.INSTANCE, "0x00401003", "Similar name eol comment.",
"NO_ADDRESS");
checkMarkupDestinationSource(VTHashedFunctionAddressCorrelation.NAME, true);
runCorrelator(new SimilarSymbolNameProgramCorrelatorFactory());
selectMatch("0x00401000", "0x00402000");
validateCommentMarkupItems(EolCommentMarkupType.INSTANCE, "0x00401003",
"Similar name eol comment.", "NO_ADDRESS");
validateMarkupDestinationAddress(VTHashedFunctionAddressCorrelation.NAME, true);
}
@Test
@ -193,23 +206,24 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
// processors with matching instructions.
Program p1 = buildProgram1("language1");
Program p2 = buildProgram2("language2");
createSession(p1, p2);
vtTestEnv.showTool();
addComment(CodeUnit.PLATE_COMMENT, "0x00401000", "First plate comment.");
addComment(CodeUnit.PLATE_COMMENT, "0x00401003", "Second plate comment.");
addProgramCorrelation(new SimilarSymbolNameProgramCorrelatorFactory());
useMatch("0x00401000", "0x00402000");
checkAddressCorrelation(LinearFunctionAddressCorrelation.NAME);
runCorrelator(new SimilarSymbolNameProgramCorrelatorFactory());
selectMatch("0x00401000", "0x00402000");
// Verify the entry point plate comment markup has a destination address.
checkCommentMarkup(PlateCommentMarkupType.INSTANCE, "0x00401000", "First plate comment.",
"0x00402000");
assertEquals(addr("0x00402000", p2), getMatchingDestAddress("0x00401000")); // Expects a correlated address.
// Verify the non-entry point plate comment markup also has a destination address.
checkCommentMarkup(PlateCommentMarkupType.INSTANCE, "0x00401003", "Second plate comment.",
"0x00402003");
assertEquals(addr("0x00402003", p2), getMatchingDestAddress("0x00401003")); // Expects a correlated address.
checkMarkupDestinationSource(LinearFunctionAddressCorrelation.NAME, true);
validateCommentMarkupItems(PlateCommentMarkupType.INSTANCE, "0x00401000",
"First plate comment.", "0x00402000");
// The non-entry point plate comment markup has no address found when using the
// Code Compare correlators
validateCommentMarkupItems(PlateCommentMarkupType.INSTANCE, "0x00401003",
"Second plate comment.", "NO_ADDRESS");
validateMarkupDestinationAddress(CodeCompareAddressCorrelation.NAME, true);
}
@Test
@ -219,53 +233,29 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
// function entry point as the destination. This uses a function match created by
// the Similar Symbol Name correlator where the two programs are for different
// languages but the same processor with different instructions.
Program languageProgram1 = buildProgram1("language1");
Program languageProgram2 = buildProgram3("language3");
createSession(languageProgram1, languageProgram2);
Program p1 = buildProgram1("language1");
Program p2 = buildProgram3("language3");
createSession(p1, p2);
vtTestEnv.showTool();
addComment(CodeUnit.PLATE_COMMENT, "0x00401000", "First plate comment.");
addComment(CodeUnit.PLATE_COMMENT, "0x00401003", "Second plate comment.");
addProgramCorrelation(new SimilarSymbolNameProgramCorrelatorFactory());
useMatch("0x00401000", "0x00402000");
checkAddressCorrelation(VTHashedFunctionAddressCorrelation.NAME);
runCorrelator(new SimilarSymbolNameProgramCorrelatorFactory());
selectMatch("0x00401000", "0x00402000");
// Verify the entry point plate comment markup has a destination address.
checkCommentMarkup(PlateCommentMarkupType.INSTANCE, "0x00401000", "First plate comment.",
"0x00402000");
assertNull(getMatchingDestAddress("0x00401000")); // Expects no correlated address.
validateCommentMarkupItems(PlateCommentMarkupType.INSTANCE, "0x00401000",
"First plate comment.", "0x00402000");
// Verify the non-entry point plate comment markup does not have a destination address.
checkCommentMarkup(PlateCommentMarkupType.INSTANCE, "0x00401003", "Second plate comment.",
"NO_ADDRESS");
assertNull(getMatchingDestAddress("0x00401003")); // Expects no correlated address.
checkMarkupDestinationSource(VTHashedFunctionAddressCorrelation.NAME, true);
validateCommentMarkupItems(PlateCommentMarkupType.INSTANCE, "0x00401003",
"Second plate comment.", "NO_ADDRESS");
validateMarkupDestinationAddress(VTHashedFunctionAddressCorrelation.NAME, true);
}
//==================================================================================================
// Helper Methods
//==================================================================================================
/**
* Gets the destination address that has been correlated to the indicated source address
* for the current function match that has been established in the test.
* @param srcAddressStr the source address
* @return the matching destination address. Otherwise null if the address correlation for
* the match couldn't determine a matching address.
*/
private Address getMatchingDestAddress(String srcAddressStr) {
Address srcAddress = addr(srcAddressStr, sourceProgram);
AddressCorrelation actualCorrelator =
controller.getCorrelator(sourceFunction, destinationFunction);
AddressRange destRange = null;
try {
destRange =
actualCorrelator.getCorrelatedDestinationRange(srcAddress, TaskMonitor.DUMMY);
}
catch (CancelledException e) {
// Do nothing. let this return null.
}
return (destRange != null) ? destRange.getMinAddress() : null;
}
private Program buildProgram1(String name) throws Exception {
ProgramBuilder builder = new ProgramBuilder(name, ProgramBuilder._X86);
try {
@ -357,7 +347,7 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
* when creating matches.
* @param correlatorFactory the factory for the desired program correlator.
*/
protected void addProgramCorrelation(VTProgramCorrelatorFactory correlatorFactory) {
protected void runCorrelator(VTProgramCorrelatorFactory correlatorFactory) {
try {
correlator = vtTestEnv.correlate(correlatorFactory, null, TaskMonitor.DUMMY);
}
@ -374,22 +364,6 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
Boolean.TRUE);
}
/**
* Checks the address correlation being used for the current testMatch and its current
* sourceFunction and destinationFunction to verify it is the one indicated by the
* addressCorrelationName.
* @param addressCorrelationName the name of the expected address correlation for determining
* the destination address of markup for the current function match.
*/
private void checkAddressCorrelation(String addressCorrelationName) {
AddressCorrelation actualCorrelator =
controller.getCorrelator(sourceFunction, destinationFunction);
String actualCorrelatorName = actualCorrelator.getName();
assertTrue("Unexpected address correlation of " + actualCorrelatorName +
" when expecting " + addressCorrelationName + ".",
actualCorrelatorName.equals(addressCorrelationName));
}
/**
* Checks all the markup items for the testMatch to see that their destination address
* has been determined by the address correlation that is indicated by the addressCorrelationName
@ -397,7 +371,7 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
* @param addressCorrelationName the name of the expected address correlation for determining
* the destination address of non-function entry point markup items.
*/
private void checkMarkupDestinationSource(String addressCorrelationName,
private void validateMarkupDestinationAddress(String addressCorrelationName,
boolean canBeNoAddress) {
Collection<VTMarkupItem> appliableMarkupItems =
controller.getMatchInfo(testMatch).getAppliableMarkupItems(TaskMonitor.DUMMY); // Initialize the cache.
@ -430,7 +404,7 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
* @param destination the destination address
* @return the match or null if the indicated match isn't found.
*/
protected VTMatch getMatch(Address source, Address destination) {
private VTMatch getMatch(Address source, Address destination) {
List<VTMatchSet> matchSets = session.getMatchSets();
// Get matchSet 2 since 0 is manual matches and 1 is implied matches.
VTMatchSet vtMatchSet = matchSets.get(2);
@ -448,7 +422,7 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
* @param sourceAddressString the source address of the match's association.
* @param destinationAddressString the destination address of the match's association.
*/
protected void useMatch(String sourceAddressString, String destinationAddressString) {
private void selectMatch(String sourceAddressString, String destinationAddressString) {
sourceAddress = addr(sourceAddressString, sourceProgram);
destinationAddress = addr(destinationAddressString, destinationProgram);
@ -488,13 +462,13 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
* @param desiredCommentMarkupType the comment markup type we are checking
* @param sourceAddressString the source address of the markup
* @param comment the expected comment
* @param destinationAddressString the expected destination address for the markup
* @param expectedDestAddrString the expected destination address for the markup
*/
private void checkCommentMarkup(VTMarkupType desiredCommentMarkupType,
String sourceAddressString, String comment, String destinationAddressString) {
private void validateCommentMarkupItems(VTMarkupType desiredCommentMarkupType,
String sourceAddressString, String comment, String expectedDestAddrString) {
Address srcAddress = addr(sourceAddressString, sourceProgram);
Address destAddress = destinationAddressString.equals("NO_ADDRESS") ? Address.NO_ADDRESS
: addr(destinationAddressString, destinationProgram);
Address expectedDestAddr = expectedDestAddrString.equals("NO_ADDRESS") ? Address.NO_ADDRESS
: addr(expectedDestAddrString, destinationProgram);
Collection<VTMarkupItem> appliableMarkupItems =
controller.getMatchInfo(testMatch).getAppliableMarkupItems(TaskMonitor.DUMMY); // Initialize the cache.
@ -521,18 +495,19 @@ public class AddressCorrelationTest extends AbstractGhidraHeadedIntegrationTest
}
boolean isNoAddress =
markupDestAddress == null || markupDestAddress == Address.NO_ADDRESS;
if (destAddress == Address.NO_ADDRESS) {
if (expectedDestAddr == Address.NO_ADDRESS) {
assertTrue("Unexpected destination address of NO_ADDRESS for " +
vtMarkupItem.getMarkupType().getDisplayName() + " markup @ " +
vtMarkupItem.getSourceAddress().toString() + ".", isNoAddress);
return;
}
assertTrue(
"Unexpected destination address of " + markupDestAddress.toString() +
" when expecting " + destAddress.toString() + " for " +
" when expecting " + expectedDestAddr.toString() + " for " +
vtMarkupItem.getMarkupType().getDisplayName() + " markup @ " +
vtMarkupItem.getSourceAddress().toString() + ".",
markupDestAddress.equals(destAddress));
markupDestAddress.equals(expectedDestAddr));
return;
}
}

View file

@ -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.
@ -35,10 +34,10 @@ import ghidra.util.datastruct.LRUMap;
public class FixedSizeMRUCachingFactory<K, V> implements Factory<K, V> {
private LRUMap<K, V> cache;
private Factory<K, V> delegate;
private Factory<K, V> factory;
public FixedSizeMRUCachingFactory(Factory<K, V> factory, int size) {
this.delegate = factory;
this.factory = factory;
this.cache = new LRUMap<K, V>(size);
}
@ -49,7 +48,7 @@ public class FixedSizeMRUCachingFactory<K, V> implements Factory<K, V> {
return value;
}
value = delegate.get(key);
value = factory.get(key);
cache.put(key, value);
return value;
}

View file

@ -16,7 +16,6 @@
package ghidra.program.util;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -31,19 +30,20 @@ public interface AddressCorrelation {
* Returns the AddressRange of a set of addresses in the destination
* program that correlates to corresponding range in the source program.
*
* @param sourceAddress
* the source program address
* @param sourceAddress the source program address
* @param monitor the task monitor
* @return the destination program address range, or null if the source program address maps
* to one that is "deleted" in the destination program
* @return the destination program address range, or null if there is not address range mapped
* @throws CancelledException if cancelled
*/
public AddressRange getCorrelatedDestinationRange(Address sourceAddress, TaskMonitor monitor)
throws CancelledException;
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
TaskMonitor monitor) throws CancelledException;
/**
* Returns the name of the correlating algorithm.
* @return the name of the correlating algorithm.
* This method is no longer part of the API. Leaving a default implementation to reduce
* breaking clients.
* @return the simple class name of the implementing class
*/
public String getName();
public default String getName() {
return getClass().getSimpleName();
}
}

View file

@ -0,0 +1,48 @@
/* ###
* 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.program.util;
import java.util.Objects;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
/**
* A simple object that holds an {@link AddressCorrelation} address range and then name of the
* correlation.s
*/
public class AddressCorrelationRange {
private AddressRange range;
private String correlatorName;
public AddressCorrelationRange(AddressRange range, String correlatorName) {
this.range = Objects.requireNonNull(range);
this.correlatorName = Objects.requireNonNull(correlatorName);
}
public Address getMinAddress() {
return range.getMinAddress();
}
public AddressRange getRange() {
return range;
}
public String getCorrelatorName() {
return correlatorName;
}
}

View file

@ -23,9 +23,34 @@ import ghidra.program.model.listing.Function;
/**
* Interface for address correlation algorithms that can generate an address mapping from one
* set of program addresses to another.
* <p>
* This interface supplies a {@link #getPriority() priority} of {@link #DEFAULT_PRIORITY}.
* {@link DiscoverableAddressCorrelator discoverable} correlators can change this priority to be a
* lower value to be run before the supplied system correlators. Generally, the more specific or
* restrictive a correlator, the earlier (higher priority) it should be.
*/
public interface AddressCorrelator {
/**
* The default priority. This applies to client-supplied {@link DiscoverableAddressCorrelator}s
*/
public static final int DEFAULT_PRIORITY = 500;
/**
* A high priority (low number value) for correlators that should used before other correlators
*/
public static final int EARLY_PRIORITY = 100;
/**
* A low priority (high number value) for correlators that should used after other correlators
*/
public static final int LATE_CHANCE_PRIORITY = 1000;
/**
* A value used to raise or lower priorities.
*/
public static final int PRIORITY_OFFSET = 10;
/**
* Returns an address mapping from one function to another.
* @param sourceFunction the source function.
@ -61,4 +86,18 @@ public interface AddressCorrelator {
* @return the options with the default settings for this correlator.
*/
public Options getDefaultOptions();
/**
* Returns a number based on an arbitrary number scheme that dictates the order that correlators
* should be used. If a correlator returns a null value from one of the {@code correlate()}
* methods, then the next highest priority correlator will be called, and so on until a non-null
* correlation is found or all correlators have been called.
* <p>
* A lower number value is a higher priority. See {@link #DEFAULT_PRIORITY}.
*
* @return the priority
*/
public default int getPriority() {
return DEFAULT_PRIORITY;
}
}

View file

@ -15,7 +15,8 @@
*/
package ghidra.program.util;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRangeImpl;
import ghidra.program.model.listing.Data;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -30,13 +31,14 @@ public class LinearDataAddressCorrelation implements AddressCorrelation {
}
@Override
public AddressRange getCorrelatedDestinationRange(Address sourceAddress, TaskMonitor monitor)
throws CancelledException {
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
TaskMonitor monitor) throws CancelledException {
long offset = sourceAddress.getOffset();
long base = sourceData.getAddress().getOffset();
long delta = offset - base;
Address address = destinationData.getAddress().add(delta);
return new AddressRangeImpl(address, address);
AddressRangeImpl range = new AddressRangeImpl(address, address);
return new AddressCorrelationRange(range, getName());
}
@Override

View file

@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.api.correlator.address;
package ghidra.program.util;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.program.util.AddressCorrelation;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -31,7 +31,7 @@ public class LinearFunctionAddressCorrelation implements AddressCorrelation {
private final Function sourceFunction;
private final Function destinationFunction;
LinearFunctionAddressCorrelation(Function sourceFunction, Function destinationFunction) {
public LinearFunctionAddressCorrelation(Function sourceFunction, Function destinationFunction) {
this.sourceFunction = sourceFunction;
this.destinationFunction = destinationFunction;
}
@ -42,8 +42,8 @@ public class LinearFunctionAddressCorrelation implements AddressCorrelation {
}
@Override
public AddressRange getCorrelatedDestinationRange(Address sourceAddress, TaskMonitor monitor)
throws CancelledException {
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
TaskMonitor monitor) throws CancelledException {
initialize(monitor);
AddressRange toRange = cachedForwardAddressMap.get(sourceAddress);
if (toRange == null) {
@ -51,7 +51,7 @@ public class LinearFunctionAddressCorrelation implements AddressCorrelation {
Address destinationAddress = getDestinationAddress(percentOffset);
toRange = new AddressRangeImpl(destinationAddress, destinationAddress);
}
return toRange;
return new AddressCorrelationRange(toRange, getName());
}
private void initialize(TaskMonitor monitor) {
@ -66,9 +66,7 @@ public class LinearFunctionAddressCorrelation implements AddressCorrelation {
long accumulatedLength = 0;
Iterator<AddressRange> iterator = srcBody.iterator();
while (iterator.hasNext()) {
AddressRange range = iterator.next();
for (AddressRange range : srcBody) {
if (range.getMaxAddress().compareTo(address) < 0) {
accumulatedLength += range.getLength();
}