mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Updated some copy actions to use a task monitor
This commit is contained in:
parent
f3ebcf679b
commit
49a3dcebe7
3 changed files with 121 additions and 52 deletions
|
@ -49,6 +49,7 @@ import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.task.CancellableIterator;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import util.CollectionUtils;
|
import util.CollectionUtils;
|
||||||
|
|
||||||
|
@ -184,22 +185,22 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
public Transferable copySpecial(ClipboardType copyType, TaskMonitor monitor) {
|
public Transferable copySpecial(ClipboardType copyType, TaskMonitor monitor) {
|
||||||
|
|
||||||
if (copyType == ADDRESS_TEXT_TYPE) {
|
if (copyType == ADDRESS_TEXT_TYPE) {
|
||||||
return copyAddress();
|
return copyAddress(monitor);
|
||||||
}
|
}
|
||||||
else if (copyType == ADDRESS_TEXT_WITH_OFFSET_TYPE) {
|
else if (copyType == ADDRESS_TEXT_WITH_OFFSET_TYPE) {
|
||||||
return copySymbolString();
|
return copySymbolString(monitor);
|
||||||
}
|
}
|
||||||
else if (copyType == CODE_TEXT_TYPE) {
|
else if (copyType == CODE_TEXT_TYPE) {
|
||||||
return copyCode(monitor);
|
return copyCode(monitor);
|
||||||
}
|
}
|
||||||
else if (copyType == LABELS_COMMENTS_TYPE) {
|
else if (copyType == LABELS_COMMENTS_TYPE) {
|
||||||
return copyLabelsComments(true, true);
|
return copyLabelsComments(true, true, monitor);
|
||||||
}
|
}
|
||||||
else if (copyType == LABELS_TYPE) {
|
else if (copyType == LABELS_TYPE) {
|
||||||
return copyLabelsComments(true, false);
|
return copyLabelsComments(true, false, monitor);
|
||||||
}
|
}
|
||||||
else if (copyType == COMMENTS_TYPE) {
|
else if (copyType == COMMENTS_TYPE) {
|
||||||
return copyLabelsComments(false, true);
|
return copyLabelsComments(false, true, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return copyBytes(copyType, monitor);
|
return copyBytes(copyType, monitor);
|
||||||
|
@ -308,17 +309,18 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
return new NonLabelStringTransferable(location.getOperandRepresentation());
|
return new NonLabelStringTransferable(location.getOperandRepresentation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Transferable copyAddress() {
|
private Transferable copyAddress(TaskMonitor monitor) {
|
||||||
AddressSetView addrs = getSelectedAddresses();
|
AddressSetView addrs = getSelectedAddresses();
|
||||||
Iterable<Address> it = addrs.getAddresses(true);
|
Iterable<Address> iterable = addrs.getAddresses(true);
|
||||||
|
CancellableIterator<Address> it = new CancellableIterator<>(iterable.iterator(), monitor);
|
||||||
return createStringTransferable(StringUtils.join(it, "\n"));
|
return createStringTransferable(StringUtils.join(it, "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Transferable copySymbolString() {
|
private Transferable copySymbolString(TaskMonitor monitor) {
|
||||||
Listing listing = currentProgram.getListing();
|
Listing listing = currentProgram.getListing();
|
||||||
List<String> strings = new ArrayList<>();
|
List<String> strings = new ArrayList<>();
|
||||||
CodeUnitIterator codeUnits = listing.getCodeUnits(getSelectedAddresses(), true);
|
CodeUnitIterator codeUnits = listing.getCodeUnits(getSelectedAddresses(), true);
|
||||||
while (codeUnits.hasNext()) {
|
while (codeUnits.hasNext() && !monitor.isCancelled()) {
|
||||||
CodeUnit cu = codeUnits.next();
|
CodeUnit cu = codeUnits.next();
|
||||||
Address addr = cu.getAddress();
|
Address addr = cu.getAddress();
|
||||||
Function function = listing.getFunctionContaining(addr);
|
Function function = listing.getFunctionContaining(addr);
|
||||||
|
@ -379,11 +381,12 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
return createStringTransferable(copyBytesAsString(set, false, TaskMonitor.DUMMY));
|
return createStringTransferable(copyBytesAsString(set, false, TaskMonitor.DUMMY));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodeUnitInfoTransferable copyLabelsComments(boolean copyLabels, boolean copyComments) {
|
private CodeUnitInfoTransferable copyLabelsComments(boolean copyLabels, boolean copyComments,
|
||||||
|
TaskMonitor monitor) {
|
||||||
AddressSetView addressSet = getSelectedAddresses();
|
AddressSetView addressSet = getSelectedAddresses();
|
||||||
List<CodeUnitInfo> list = new ArrayList<>();
|
List<CodeUnitInfo> list = new ArrayList<>();
|
||||||
Address startAddr = addressSet.getMinAddress();
|
Address startAddr = addressSet.getMinAddress();
|
||||||
getCodeUnitInfo(addressSet, startAddr, list, copyLabels, copyComments);
|
getCodeUnitInfo(addressSet, startAddr, list, copyLabels, copyComments, monitor);
|
||||||
return new CodeUnitInfoTransferable(list);
|
return new CodeUnitInfoTransferable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,23 +492,23 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getCodeUnitInfo(AddressSetView set, Address startAddr, List<CodeUnitInfo> list,
|
private void getCodeUnitInfo(AddressSetView set, Address startAddr, List<CodeUnitInfo> list,
|
||||||
boolean copyLabels, boolean copyComments) {
|
boolean copyLabels, boolean copyComments, TaskMonitor monitor) {
|
||||||
Map<Address, CodeUnitInfo> map = new HashMap<>();
|
Map<Address, CodeUnitInfo> map = new HashMap<>();
|
||||||
if (copyLabels) {
|
if (copyLabels) {
|
||||||
getFunctions(startAddr, set, list, map);
|
getFunctions(startAddr, set, list, map, monitor);
|
||||||
getLabels(startAddr, set, list, map);
|
getLabels(startAddr, set, list, map, monitor);
|
||||||
}
|
}
|
||||||
if (copyComments) {
|
if (copyComments) {
|
||||||
getComments(startAddr, set, list, map);
|
getComments(startAddr, set, list, map, monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getFunctions(Address startAddr, AddressSetView set, List<CodeUnitInfo> list,
|
private void getFunctions(Address startAddr, AddressSetView set, List<CodeUnitInfo> list,
|
||||||
Map<Address, CodeUnitInfo> map) {
|
Map<Address, CodeUnitInfo> map, TaskMonitor monitor) {
|
||||||
|
|
||||||
FunctionIterator iter = currentProgram.getListing().getFunctions(set, true);
|
FunctionIterator it = currentProgram.getListing().getFunctions(set, true);
|
||||||
while (iter.hasNext()) {
|
while (it.hasNext() && !monitor.isCancelled()) {
|
||||||
Function function = iter.next();
|
Function function = it.next();
|
||||||
Address entry = function.getEntryPoint();
|
Address entry = function.getEntryPoint();
|
||||||
CodeUnitInfo info = getInfoFromMap(list, map, entry, startAddr);
|
CodeUnitInfo info = getInfoFromMap(list, map, entry, startAddr);
|
||||||
info.setFunction(function);
|
info.setFunction(function);
|
||||||
|
@ -513,13 +516,12 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getComments(Address startAddr, AddressSetView set, List<CodeUnitInfo> list,
|
private void getComments(Address startAddr, AddressSetView set, List<CodeUnitInfo> list,
|
||||||
Map<Address, CodeUnitInfo> map) {
|
Map<Address, CodeUnitInfo> map, TaskMonitor monitor) {
|
||||||
|
|
||||||
CodeUnitIterator iter =
|
Listing listing = currentProgram.getListing();
|
||||||
currentProgram.getListing().getCodeUnitIterator(CodeUnit.COMMENT_PROPERTY, set, true);
|
CodeUnitIterator it = listing.getCodeUnitIterator(CodeUnit.COMMENT_PROPERTY, set, true);
|
||||||
|
while (it.hasNext() && !monitor.isCancelled()) {
|
||||||
while (iter.hasNext()) {
|
CodeUnit cu = it.next();
|
||||||
CodeUnit cu = iter.next();
|
|
||||||
Address minAddress = cu.getMinAddress();
|
Address minAddress = cu.getMinAddress();
|
||||||
CodeUnitInfo info = getInfoFromMap(list, map, minAddress, startAddr);
|
CodeUnitInfo info = getInfoFromMap(list, map, minAddress, startAddr);
|
||||||
setCommentInfo(cu, info);
|
setCommentInfo(cu, info);
|
||||||
|
@ -537,12 +539,11 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getLabels(Address startAddr, AddressSetView set, List<CodeUnitInfo> list,
|
private void getLabels(Address startAddr, AddressSetView set, List<CodeUnitInfo> list,
|
||||||
Map<Address, CodeUnitInfo> map) {
|
Map<Address, CodeUnitInfo> map, TaskMonitor monitor) {
|
||||||
|
|
||||||
SymbolIterator iter = currentProgram.getSymbolTable().getPrimarySymbolIterator(set, true);
|
SymbolIterator it = currentProgram.getSymbolTable().getPrimarySymbolIterator(set, true);
|
||||||
|
while (it.hasNext() && !monitor.isCancelled()) {
|
||||||
while (iter.hasNext()) {
|
Symbol symbol = it.next();
|
||||||
Symbol symbol = iter.next();
|
|
||||||
Address minAddress = symbol.getAddress();
|
Address minAddress = symbol.getAddress();
|
||||||
Symbol[] symbols = currentProgram.getSymbolTable().getSymbols(minAddress);
|
Symbol[] symbols = currentProgram.getSymbolTable().getSymbols(minAddress);
|
||||||
CodeUnitInfo info = getInfoFromMap(list, map, minAddress, startAddr);
|
CodeUnitInfo info = getInfoFromMap(list, map, minAddress, startAddr);
|
||||||
|
|
|
@ -24,20 +24,23 @@ import org.apache.commons.collections4.IteratorUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import ghidra.util.task.CancellableIterator;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of utility methods that prevent you from having to do unsafe casts of
|
* A collection of utility methods that prevent you from having to do unsafe casts of
|
||||||
* {@link Collection} classes due to runtime type erasure.
|
* {@link Collection} classes due to runtime type erasure.
|
||||||
*
|
*
|
||||||
* <P>Be sure to check Apache collection utils before using this class, as it's a
|
* <P>Be sure to check Apache collection utils before using this class, as it's a
|
||||||
* standard utility and often more efficient.
|
* standard utility and often more efficient.
|
||||||
*
|
*
|
||||||
* <P>Some examples:
|
* <P>Some examples:
|
||||||
* <OL>
|
* <OL>
|
||||||
* <LI>{@link org.apache.commons.collections4.CollectionUtils}</LI>
|
* <LI>{@link org.apache.commons.collections4.CollectionUtils}</LI>
|
||||||
* <LI>{@link IterableUtils}</LI>
|
* <LI>{@link IterableUtils}</LI>
|
||||||
* <LI>{@link IteratorUtils}</LI>
|
* <LI>{@link IteratorUtils}</LI>
|
||||||
* <LI>{@link StringUtils#join(Iterable, char)} - for pretty printing collections with newlines</LI>
|
* <LI>{@link StringUtils#join(Iterable, char)} - for pretty printing collections with newlines</LI>
|
||||||
* <LI><code>Apache CollectionUtils.collect(Collection, Transformer)</code> - to turn a
|
* <LI><code>Apache CollectionUtils.collect(Collection, Transformer)</code> - to turn a
|
||||||
* collection in to collection of strings when the default <code>toString()</code> is lacking</LI>
|
* collection in to collection of strings when the default <code>toString()</code> is lacking</LI>
|
||||||
* </OL>
|
* </OL>
|
||||||
*/
|
*/
|
||||||
|
@ -50,7 +53,7 @@ public class CollectionUtils {
|
||||||
/**
|
/**
|
||||||
* Turns the given items into a set. If there is only a single item and it is null, then
|
* Turns the given items into a set. If there is only a single item and it is null, then
|
||||||
* an empty set will be returned.
|
* an empty set will be returned.
|
||||||
*
|
*
|
||||||
* @param items the items to put in the set
|
* @param items the items to put in the set
|
||||||
* @return the list of items
|
* @return the list of items
|
||||||
*/
|
*/
|
||||||
|
@ -85,8 +88,8 @@ public class CollectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drains the given iterator into a new Set
|
* Drains the given iterator into a new Set
|
||||||
*
|
*
|
||||||
* @param it the iterator
|
* @param it the iterator
|
||||||
* @return the set
|
* @return the set
|
||||||
*/
|
*/
|
||||||
public static <T> Set<T> asSet(Iterator<T> it) {
|
public static <T> Set<T> asSet(Iterator<T> it) {
|
||||||
|
@ -104,9 +107,9 @@ public class CollectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns the given iterable into a new Set, returning it directly if it is a set, draining
|
* Turns the given iterable into a new Set, returning it directly if it is a set, draining
|
||||||
* it into a set if it is not already.
|
* it into a set if it is not already.
|
||||||
*
|
*
|
||||||
* @param iterable the iterable
|
* @param iterable the iterable
|
||||||
* @return the set
|
* @return the set
|
||||||
*/
|
*/
|
||||||
public static <T> Set<T> asSet(Iterable<T> iterable) {
|
public static <T> Set<T> asSet(Iterable<T> iterable) {
|
||||||
|
@ -129,9 +132,9 @@ public class CollectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link Arrays#asList(Object...)}, except that this method will turn a single
|
* Similar to {@link Arrays#asList(Object...)}, except that this method will turn a single
|
||||||
* null parameter into an empty list. Also, this method creates a new, mutable array,
|
* null parameter into an empty list. Also, this method creates a new, mutable array,
|
||||||
* whereas the former's array is not mutable.
|
* whereas the former's array is not mutable.
|
||||||
*
|
*
|
||||||
* @param items the items to add to the list
|
* @param items the items to add to the list
|
||||||
* @return the list
|
* @return the list
|
||||||
*/
|
*/
|
||||||
|
@ -361,7 +364,7 @@ public class CollectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the given array is null or has 0 length
|
* Returns true if the given array is null or has 0 length
|
||||||
*
|
*
|
||||||
* @param c the collection to check
|
* @param c the collection to check
|
||||||
* @return true if blank
|
* @return true if blank
|
||||||
*/
|
*/
|
||||||
|
@ -371,7 +374,7 @@ public class CollectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the given array is null or has 0 length
|
* Returns true if the given array is null or has 0 length
|
||||||
*
|
*
|
||||||
* @param t the items to check
|
* @param t the items to check
|
||||||
* @return true if blank
|
* @return true if blank
|
||||||
*/
|
*/
|
||||||
|
@ -399,9 +402,9 @@ public class CollectionUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines all collections passed-in into a pass-through not creating a new collection)
|
* Combines all collections passed-in into a pass-through (not creating a new collection)
|
||||||
* Iterable.
|
* Iterable.
|
||||||
*
|
*
|
||||||
* @param iterables the iterables to combine
|
* @param iterables the iterables to combine
|
||||||
* @return the iterable
|
* @return the iterable
|
||||||
*/
|
*/
|
||||||
|
@ -411,9 +414,26 @@ public class CollectionUtils {
|
||||||
return asIterable(s.iterator());
|
return asIterable(s.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combines all collections passed-in into a pass-through (not creating a new collection)
|
||||||
|
* Iterable that uses the given task monitor.
|
||||||
|
*
|
||||||
|
* @param monitor a task monitor that allows for cancelling iteration
|
||||||
|
* @param iterables the iterables to combine
|
||||||
|
* @return the iterable
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T> Iterable<T> asCancellableIterable(TaskMonitor monitor,
|
||||||
|
Iterable<T>... iterables) {
|
||||||
|
Stream<T> s = asStream(iterables);
|
||||||
|
Iterator<T> it = s.iterator();
|
||||||
|
CancellableIterator<T> cancellable = new CancellableIterator<>(it, monitor);
|
||||||
|
return asIterable(cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns the given iterator into a stream
|
* Turns the given iterator into a stream
|
||||||
*
|
*
|
||||||
* @param iterator the iterator
|
* @param iterator the iterator
|
||||||
* @return the stream
|
* @return the stream
|
||||||
*/
|
*/
|
||||||
|
@ -422,15 +442,15 @@ public class CollectionUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines all iterables passed-in into a pass-through (not creating a new collection) Stream.
|
* Combines all iterables passed-in into a pass-through (not creating a new collection) Stream.
|
||||||
*
|
*
|
||||||
* @param iterables the iterables to combine
|
* @param iterables the iterables to combine
|
||||||
* @return the stream
|
* @return the stream
|
||||||
*/
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public static <T> Stream<T> asStream(Iterable<T>... iterables) {
|
public static <T> Stream<T> asStream(Iterable<T>... iterables) {
|
||||||
Stream<T> s = Stream.of(iterables)
|
Stream<T> s =
|
||||||
.flatMap(e -> StreamSupport.stream(e.spliterator(), false));
|
Stream.of(iterables).flatMap(e -> StreamSupport.stream(e.spliterator(), false));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.util.task;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link Iterator} wrapper that allows clients to use a task monitor to cancel iteration
|
||||||
|
*
|
||||||
|
* @param <T> the type
|
||||||
|
*/
|
||||||
|
public class CancellableIterator<T> implements Iterator<T> {
|
||||||
|
|
||||||
|
private Iterator<T> delegate;
|
||||||
|
private TaskMonitor monitor;
|
||||||
|
|
||||||
|
public CancellableIterator(Iterator<T> delegate, TaskMonitor monitor) {
|
||||||
|
this.delegate = Objects.requireNonNull(delegate);
|
||||||
|
this.monitor = Objects.requireNonNull(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
if (monitor.isCancelled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return delegate.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
return delegate.next();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue