From 0fbd23653d27756a63026333852ed8169196270f Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 23 Jul 2024 18:01:38 -0400 Subject: [PATCH] Fixed tests failing to recent Version Tracking updates. Added a priority to Version Tracking address correlators. --- .../ghidra/app/services/AnalysisPriority.java | 17 +- .../CodeCompareAddressCorrelation.java | 16 +- .../CodeCompareAddressCorrelator.java | 19 +- Ghidra/Features/VersionTracking/build.gradle | 6 +- ...ator.java => LinearAddressCorrelator.java} | 18 +- .../address/StraightLineCorrelation.java | 49 ++-- .../VTHashedFunctionAddressCorrelation.java | 21 +- .../VTHashedFunctionAddressCorrelator.java | 72 ++++++ .../feature/vt/api/main/VTMarkupItem.java | 9 +- .../markuptype/PlateCommentMarkupType.java | 19 +- .../gui/plugin/AddressCorrelatorManager.java | 45 +++- .../matchtable/VTMatchTableProvider.java | 19 +- .../feature/vt/gui/task/ClearMatchTask.java | 15 +- .../vt/gui/task/UnapplyMarkupItemTask.java | 12 +- .../vt/gui/util/ImpliedMatchUtils.java | 8 +- .../ghidra/feature/vt/gui/util/MatchInfo.java | 35 +-- .../feature/vt/api/VTControllerTest.java | 16 +- .../address/AddressCorrelationTest.java | 221 ++++++++---------- .../cache/FixedSizeMRUCachingFactory.java | 11 +- .../program/util/AddressCorrelation.java | 24 +- .../program/util/AddressCorrelationRange.java | 48 ++++ .../program/util/AddressCorrelator.java | 43 +++- .../util/LinearDataAddressCorrelation.java | 14 +- .../LinearFunctionAddressCorrelation.java | 24 +- 24 files changed, 488 insertions(+), 293 deletions(-) rename Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/{LastResortAddressCorrelator.java => LinearAddressCorrelator.java} (81%) create mode 100644 Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelator.java create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelationRange.java rename Ghidra/{Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address => Framework/SoftwareModeling/src/main/java/ghidra/program/util}/LinearFunctionAddressCorrelation.java (88%) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/services/AnalysisPriority.java b/Ghidra/Features/Base/src/main/java/ghidra/app/services/AnalysisPriority.java index f81c188b6b..b37dd6d7fd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/services/AnalysisPriority.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/services/AnalysisPriority.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -43,7 +43,6 @@ public class AnalysisPriority { * happen with a low priority. * */ - /** * Defines a full format analysis as the first priority for automatic analysis. @@ -78,7 +77,7 @@ public class AnalysisPriority { * instructions AnalyzerType.INSTRUCTIONS. 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) { diff --git a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelation.java b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelation.java index d5f601330b..c2de2d952f 100755 --- a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelation.java +++ b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelation.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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 CUCOMPARATOR = new Comparator() { @@ -446,6 +450,6 @@ public class CodeCompareAddressCorrelation implements AddressCorrelation { @Override public String getName() { - return "CodeCompareAddressCorrelator"; + return NAME; } } diff --git a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelator.java b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelator.java index c68744698f..4de814f6e1 100755 --- a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelator.java +++ b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/correlator/CodeCompareAddressCorrelator.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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; + } } diff --git a/Ghidra/Features/VersionTracking/build.gradle b/Ghidra/Features/VersionTracking/build.gradle index 19eda022e1..4691cf3714 100644 --- a/Ghidra/Features/VersionTracking/build.gradle +++ b/Ghidra/Features/VersionTracking/build.gradle @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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') } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LastResortAddressCorrelator.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LinearAddressCorrelator.java similarity index 81% rename from Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LastResortAddressCorrelator.java rename to Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LinearAddressCorrelator.java index eb77363a51..73fc91724b 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LastResortAddressCorrelator.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LinearAddressCorrelator.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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; + } } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/StraightLineCorrelation.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/StraightLineCorrelation.java index a0b2234657..bf690421be 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/StraightLineCorrelation.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/StraightLineCorrelation.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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(); - 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(); @@ -82,10 +91,11 @@ public class StraightLineCorrelation implements AddressCorrelation { if (srcMnemonic.equals(destMnemonic)) { monitor.checkCancelled(); monitor.incrementProgress(srcCodeUnit.getLength()); - defineRange(cachedForwardAddressMap, srcCodeUnit, destCodeUnit); + defineRange(cachedForwardAddressMap, srcCodeUnit, destCodeUnit); } - else + else { break; // First mismatch we break out of the loop + } } computeParamCorrelation(); } @@ -124,13 +134,12 @@ 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 map, - CodeUnit sourceCodeUnit, CodeUnit destinationCodeUnit) { + private static void defineRange(Map map, CodeUnit sourceCodeUnit, + CodeUnit destinationCodeUnit) { Address minAddress = sourceCodeUnit.getMinAddress(); Address maxAddress = sourceCodeUnit.getMaxAddress(); - AddressRangeImpl toRange = - new AddressRangeImpl(destinationCodeUnit.getMinAddress(), - destinationCodeUnit.getMaxAddress()); + AddressRangeImpl toRange = new AddressRangeImpl(destinationCodeUnit.getMinAddress(), + destinationCodeUnit.getMaxAddress()); while (!minAddress.equals(maxAddress)) { map.put(minAddress, toRange); minAddress = minAddress.next(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelation.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelation.java index 6902dec99d..5bf03c2ace 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelation.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelation.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelator.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelator.java new file mode 100644 index 0000000000..9020696797 --- /dev/null +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/VTHashedFunctionAddressCorrelator.java @@ -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; + } +} diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/main/VTMarkupItem.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/main/VTMarkupItem.java index bc5771c1b8..e88225f997 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/main/VTMarkupItem.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/main/VTMarkupItem.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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 considered 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(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/markuptype/PlateCommentMarkupType.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/markuptype/PlateCommentMarkupType.java index f9fff004aa..38d731892a 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/markuptype/PlateCommentMarkupType.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/markuptype/PlateCommentMarkupType.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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; } @@ -124,7 +127,7 @@ public class PlateCommentMarkupType extends CommentMarkupType { if (vtMarkupItem.getSourceAddress().equals(association.getSourceAddress())) { // Set Plate destination to destination function's entry point. vtMarkupItem.setDefaultDestinationAddress(association.getDestinationAddress(), - VTMarkupItem.FUNCTION_ADDRESS_SOURCE); + VTMarkupItem.FUNCTION_ADDRESS_SOURCE); } } return markupItems; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/AddressCorrelatorManager.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/AddressCorrelatorManager.java index f4b7ea5758..f066bd7c9c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/AddressCorrelatorManager.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/AddressCorrelatorManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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 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 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 initializeAddressCorrelators() { List instances = ClassSearcher.getInstances(DiscoverableAddressCorrelator.class); - List addressCorrelatorList = new ArrayList(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(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; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java index 43b4986444..6a171ed8c5 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -1153,13 +1153,18 @@ public class VTMatchTableProvider extends ComponentProviderAdapter @Override public boolean isSubFilterOf(Filter otherFilter) { - if (columnFilter == null) { - return false; + + Class clazz = getClass(); + Class otherClazz = otherFilter.getClass(); + if (!clazz.equals(otherClazz)) { + return false; // must be the same class } - if (otherFilter instanceof VTColumnFilter otherColumnFilter) { - return columnFilter.isSubFilterOf(otherColumnFilter.columnFilter); + + VTColumnFilter otherColumnFilter = (VTColumnFilter) otherFilter; + if (columnFilter == null && otherColumnFilter.columnFilter == null) { + return true; } - return false; + return columnFilter.isSubFilterOf(otherColumnFilter.columnFilter); } } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/ClearMatchTask.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/ClearMatchTask.java index 7a41086f56..cbc5c1486d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/ClearMatchTask.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/ClearMatchTask.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/UnapplyMarkupItemTask.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/UnapplyMarkupItemTask.java index 101003f31e..3319578408 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/UnapplyMarkupItemTask.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/task/UnapplyMarkupItemTask.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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; @@ -42,7 +42,7 @@ public class UnapplyMarkupItemTask extends VtTask { "Unexpected condition - VTSession is not a DB object!"); } } - + @Override protected boolean shouldSuspendSessionEvents() { return markupItems.size() > 20; @@ -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(); } } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/ImpliedMatchUtils.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/ImpliedMatchUtils.java index 592daa6a57..b520b1555f 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/ImpliedMatchUtils.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/ImpliedMatchUtils.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchInfo.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchInfo.java index 5abec88cbf..21505297b5 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchInfo.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchInfo.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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, diff --git a/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/VTControllerTest.java b/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/VTControllerTest.java index 03f952afd2..f8f29a80ce 100644 --- a/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/VTControllerTest.java +++ b/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/VTControllerTest.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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)); } } diff --git a/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/correlator/address/AddressCorrelationTest.java b/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/correlator/address/AddressCorrelationTest.java index 3d4475123b..69b1b6a6f6 100644 --- a/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/correlator/address/AddressCorrelationTest.java +++ b/Ghidra/Features/VersionTracking/src/test.slow/java/ghidra/feature/vt/api/correlator/address/AddressCorrelationTest.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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 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 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 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; } } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/cache/FixedSizeMRUCachingFactory.java b/Ghidra/Framework/Generic/src/main/java/generic/cache/FixedSizeMRUCachingFactory.java index b3f85c6cf3..5953c78871 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/cache/FixedSizeMRUCachingFactory.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/cache/FixedSizeMRUCachingFactory.java @@ -1,13 +1,12 @@ /* ### * 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. * 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. @@ -35,10 +34,10 @@ import ghidra.util.datastruct.LRUMap; public class FixedSizeMRUCachingFactory implements Factory { private LRUMap cache; - private Factory delegate; + private Factory factory; public FixedSizeMRUCachingFactory(Factory factory, int size) { - this.delegate = factory; + this.factory = factory; this.cache = new LRUMap(size); } @@ -49,7 +48,7 @@ public class FixedSizeMRUCachingFactory implements Factory { return value; } - value = delegate.get(key); + value = factory.get(key); cache.put(key, value); return value; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelation.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelation.java index 6c47ad339d..331a3429a6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelation.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelation.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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(); + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelationRange.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelationRange.java new file mode 100644 index 0000000000..ad377614ec --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelationRange.java @@ -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; + } +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelator.java index c022c6b084..bc33787501 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/AddressCorrelator.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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. + *

+ * 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. + *

+ * A lower number value is a higher priority. See {@link #DEFAULT_PRIORITY}. + * + * @return the priority + */ + public default int getPriority() { + return DEFAULT_PRIORITY; + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearDataAddressCorrelation.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearDataAddressCorrelation.java index 235601b33d..1899e9d42d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearDataAddressCorrelation.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearDataAddressCorrelation.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -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 diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LinearFunctionAddressCorrelation.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearFunctionAddressCorrelation.java similarity index 88% rename from Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LinearFunctionAddressCorrelation.java rename to Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearFunctionAddressCorrelation.java index c8b5d77b20..bfcc84a9f4 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/address/LinearFunctionAddressCorrelation.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LinearFunctionAddressCorrelation.java @@ -4,22 +4,22 @@ * 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; +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 iterator = srcBody.iterator(); - while (iterator.hasNext()) { - AddressRange range = iterator.next(); + for (AddressRange range : srcBody) { if (range.getMaxAddress().compareTo(address) < 0) { accumulatedLength += range.getLength(); } @@ -125,5 +123,5 @@ public class LinearFunctionAddressCorrelation implements AddressCorrelation { } cachedForwardAddressMap.putAll(map); } - + }