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
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
* <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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/* ###
|
||||
* 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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class LinearFunctionAddressCorrelation implements AddressCorrelation {
|
||||
|
||||
public static final String NAME = "LinearFunctionAddressCorrelation";
|
||||
|
||||
private Map<Address, AddressRange> cachedForwardAddressMap;
|
||||
private final Function sourceFunction;
|
||||
private final Function destinationFunction;
|
||||
|
||||
public LinearFunctionAddressCorrelation(Function sourceFunction, Function destinationFunction) {
|
||||
this.sourceFunction = sourceFunction;
|
||||
this.destinationFunction = destinationFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressCorrelationRange getCorrelatedDestinationRange(Address sourceAddress,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
initialize(monitor);
|
||||
AddressRange toRange = cachedForwardAddressMap.get(sourceAddress);
|
||||
if (toRange == null) {
|
||||
double percentOffset = findPercentageFromFunctionStart(sourceAddress);
|
||||
Address destinationAddress = getDestinationAddress(percentOffset);
|
||||
toRange = new AddressRangeImpl(destinationAddress, destinationAddress);
|
||||
}
|
||||
return new AddressCorrelationRange(toRange, getName());
|
||||
}
|
||||
|
||||
private void initialize(TaskMonitor monitor) {
|
||||
if (cachedForwardAddressMap == null) {
|
||||
cachedForwardAddressMap = new HashMap<Address, AddressRange>();
|
||||
computeParamCorrelation();
|
||||
}
|
||||
}
|
||||
|
||||
private double findPercentageFromFunctionStart(Address address) {
|
||||
AddressSetView srcBody = sourceFunction.getBody();
|
||||
|
||||
long accumulatedLength = 0;
|
||||
|
||||
for (AddressRange range : srcBody) {
|
||||
if (range.getMaxAddress().compareTo(address) < 0) {
|
||||
accumulatedLength += range.getLength();
|
||||
}
|
||||
else {
|
||||
if (range.contains(address)) {
|
||||
accumulatedLength += address.subtract(range.getMinAddress());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double percentOffset = (double) (accumulatedLength) / srcBody.getNumAddresses();
|
||||
|
||||
return percentOffset;
|
||||
}
|
||||
|
||||
private Address getDestinationAddress(double percentOffset) {
|
||||
AddressSetView srcBody = destinationFunction.getBody();
|
||||
long offset = (long) (percentOffset * srcBody.getNumAddresses() + 0.5);
|
||||
AddressRangeIterator addressRanges = srcBody.getAddressRanges();
|
||||
while (addressRanges.hasNext()) {
|
||||
AddressRange addressRange = addressRanges.next();
|
||||
long rangeLength = addressRange.getLength();
|
||||
if (offset < rangeLength) {
|
||||
Address address = addressRange.getMinAddress().add(offset);
|
||||
return address;
|
||||
}
|
||||
offset -= rangeLength;
|
||||
}
|
||||
return srcBody.getMaxAddress();
|
||||
}
|
||||
|
||||
private void computeParamCorrelation() {
|
||||
Parameter[] sourceParameters = sourceFunction.getParameters();
|
||||
Parameter[] destinationParameters = destinationFunction.getParameters();
|
||||
if (sourceParameters.length != destinationParameters.length) {
|
||||
return;
|
||||
}
|
||||
Map<Address, AddressRange> map = new HashMap<Address, AddressRange>();
|
||||
for (int i = 0; i < sourceParameters.length; i++) {
|
||||
Parameter sourceParameter = sourceParameters[i];
|
||||
Parameter destinationParameter = destinationParameters[i];
|
||||
if (!sourceParameter.isValid() || !destinationParameter.isValid()) {
|
||||
return;
|
||||
}
|
||||
VariableStorage sourceParamStorage = sourceParameter.getVariableStorage();
|
||||
VariableStorage destParamStorage = destinationParameter.getVariableStorage();
|
||||
if (!sourceParamStorage.equals(destParamStorage)) {
|
||||
return;
|
||||
}
|
||||
Address dest = sourceParamStorage.getMinAddress();
|
||||
Address src = destParamStorage.getMinAddress();
|
||||
map.put(src, new AddressRangeImpl(dest, dest));
|
||||
}
|
||||
cachedForwardAddressMap.putAll(map);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue