mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Fixed tests failing to recent Version Tracking updates. Added a
priority to Version Tracking address correlators.
This commit is contained in:
parent
220d6d9f58
commit
0fbd23653d
24 changed files with 488 additions and 293 deletions
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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,29 +53,37 @@ 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());
|
||||
while(srcIter.hasNext() && destIter.hasNext()) {
|
||||
while (srcIter.hasNext() && destIter.hasNext()) {
|
||||
CodeUnit srcCodeUnit = srcIter.next();
|
||||
CodeUnit destCodeUnit = destIter.next();
|
||||
String srcMnemonic = srcCodeUnit.getMnemonicString();
|
||||
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue