Java Code Examples for ghidra.util.task.TaskMonitor#incrementProgress()

The following examples show how to use ghidra.util.task.TaskMonitor#incrementProgress() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DyldCacheHeader.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void markupSlideInfo(Program program, AddressSpace space, TaskMonitor monitor,
		MessageLog log) throws CancelledException {
	monitor.setMessage("Marking up DYLD slide info...");
	monitor.initialize(1);
	try {
		if (slideInfo != null) {
			Address addr = fileOffsetToAddr(slideInfoOffset, program, space);
			DataUtilities.createData(program, addr, slideInfo.toDataType(), -1, false,
				DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
		}
		monitor.incrementProgress(1);
	}
	catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
		log.appendMsg(DyldCacheHeader.class.getSimpleName(),
			"Failed to markup dyld_cache_slide_info.");
	}
}
 
Example 2
Source File: ByteTrie.java    From ghidra with Apache License 2.0 6 votes vote down vote up
/**
 * Visits all the nodes in the trie such that the visitation order is properly
 * ordered (even though the actual algorithm below is a PREORDER traversal).
 * The client is responsible for not performing actions on non-terminal nodes
 * as necessary.
 * @param monitor a task monitor
 * @param op the operation to perform
 * @throws CancelledException if the user cancels
 */
@Override
public void inorder(TaskMonitor monitor, Op<T> op) throws CancelledException {
	Stack<ByteTrieNode<T>> parentStack = new Stack<ByteTrieNode<T>>();
	parentStack.push(null);
	ByteTrieNode<T> top = root;
	monitor.initialize(numberOfNodes());
	while (top != null) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		op.op(top);
		if (top.children.length == 0) {
			top = parentStack.pop();
		}
		else {
			for (int ii = top.children.length - 1; ii > 0; --ii) {
				parentStack.push(top.children[ii]);
			}
			top = top.children[0];
		}
	}
}
 
Example 3
Source File: DyldCacheLocalSymbolsInfo.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void parseLocalSymbols(MessageLog log, TaskMonitor monitor) throws CancelledException {
	monitor.setMessage("Parsing DYLD local symbol entries...");
	monitor.initialize(entriesCount);
	reader.setPointerIndex(startIndex + entriesOffset);
	try {
		for (int i = 0; i < entriesCount; ++i) {
			localSymbolsEntryList.add(new DyldCacheLocalSymbolsEntry(reader));
			monitor.checkCanceled();
			monitor.incrementProgress(1);
		}
	}
	catch (IOException e) {
		log.appendMsg(DyldCacheAccelerateInfo.class.getSimpleName(),
			"Failed to parse dyld_cache_local_symbols_entry.");
	}
}
 
Example 4
Source File: ClosedSequenceMiner.java    From ghidra with Apache License 2.0 6 votes vote down vote up
/**
 * Mine the database for closed sequences.
 * 
 * @param monitor
 * @return The discovered sequences
 */
public Set<FrequentSequence> mineClosedSequences(TaskMonitor monitor) {
	globallyFrequentItems = database.getGloballyFrequentItems(minSupport);
	monitor.setMaximum(globallyFrequentItems.size());
	for (FrequentSequenceItem gfItem : globallyFrequentItems) {
		if (monitor.isCancelled()) {
			break;
		}
		monitor.incrementProgress(1);
		List<SequenceItem> singletonFrequentItem = new ArrayList<SequenceItem>();
		singletonFrequentItem.add(gfItem.getItem());
		ProjectedDatabase projectedDatabase =
			new ProjectedDatabase(database, singletonFrequentItem);
		Set<FrequentSequenceItem> backwardExtensionItems =
			projectedDatabase.getBackwardExtensionItems();
		if (backwardExtensionItems.size() == 0) {
			bide(projectedDatabase, monitor);
		}
	}
	return frequentClosedSequences;
}
 
Example 5
Source File: DyldCacheHeader.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void parseImageTextInfo(MessageLog log, TaskMonitor monitor) throws CancelledException {
	if (imagesTextOffset == 0) {
		return;
	}
	monitor.setMessage("Parsing DYLD image text info...");
	monitor.initialize(imagesTextCount);
	try {
		reader.setPointerIndex(imagesTextOffset);
		for (int i = 0; i < imagesTextCount; ++i) {
			imageTextInfoList.add(new DyldCacheImageTextInfo(reader));
			monitor.checkCanceled();
			monitor.incrementProgress(1);
		}
	}
	catch (IOException e) {
		log.appendMsg(DyldCacheHeader.class.getSimpleName(),
			"Failed to parse dyld_cache_image_text_info.");
	}
}
 
Example 6
Source File: DyldCacheHeader.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void markupImageInfo(Program program, AddressSpace space, TaskMonitor monitor,
		MessageLog log) throws CancelledException {
	monitor.setMessage("Marking up DYLD image info...");
	monitor.initialize(imageInfoList.size());
	try {
		Address addr = fileOffsetToAddr(imagesOffset, program, space);
		for (DyldCacheImageInfo imageInfo : imageInfoList) {
			Data d = DataUtilities.createData(program, addr, imageInfo.toDataType(), -1, false,
				DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
			program.getListing().setComment(addr, CodeUnit.EOL_COMMENT, imageInfo.getPath());
			addr = addr.add(d.getLength());
			monitor.checkCanceled();
			monitor.incrementProgress(1);
		}
	}
	catch (CodeUnitInsertionException | DuplicateNameException | IOException e) {
		log.appendMsg(DyldCacheHeader.class.getSimpleName(),
			"Failed to markup dyld_cache_image_info.");
	}
}
 
Example 7
Source File: DataTypeTreeDeleteTask.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void deleteNodes(ArchiveNode archiveNode, List<GTreeNode> list, TaskMonitor monitor)
		throws CancelledException {

	Archive archive = archiveNode.getArchive();
	DataTypeManager dataTypeManager = archive.getDataTypeManager();
	int transactionID = dataTypeManager.startTransaction("Delete Category/DataType");
	try {
		for (GTreeNode node : list) {
			monitor.checkCanceled();
			removeNode(node, monitor);
			monitor.incrementProgress(1);
		}
	}
	finally {
		dataTypeManager.endTransaction(transactionID, true);
	}
}
 
Example 8
Source File: DyldCacheAccelerateInfo.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void markupReExportList(Program program, Address accelerateInfoAddr,
		TaskMonitor monitor, MessageLog log) throws CancelledException {
	monitor.setMessage("Marking up DYLD re-exports...");
	monitor.initialize(1);
	try {
		Address addr = accelerateInfoAddr.add(reExportListOffset);
		DataType dt = new ArrayDataType(WORD, reExportCount, WORD.getLength());
		DataUtilities.createData(program, addr, dt, -1, false,
			DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
		program.getListing().setComment(addr, CodeUnit.EOL_COMMENT, "re-exports");
		monitor.incrementProgress(1);
	}
	catch (CodeUnitInsertionException e) {
		log.appendMsg(DyldCacheAccelerateInfo.class.getSimpleName(),
			"Failed to markup reExportList.");
	}
}
 
Example 9
Source File: ClearMarkupItemConsideredStatusTask.java    From ghidra with Apache License 2.0 5 votes vote down vote up
@Override
protected boolean doWork(TaskMonitor monitor) throws Exception {
	monitor.initialize(markupItems.size());
	for (VTMarkupItem markupItem : markupItems) {
		monitor.checkCanceled();
		markupItem.setConsidered(VTMarkupItemConsideredStatus.UNCONSIDERED);
		monitor.incrementProgress(1);
	}
	return true;
}
 
Example 10
Source File: DexHeaderFormatAnalyzer.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void processFields(Program program, DexHeader header, TaskMonitor monitor,
		MessageLog log) throws Exception {
	monitor.setMessage("DEX: processing fields");
	monitor.setMaximum(header.getFieldIdsSize());
	monitor.setProgress(0);
	Address address = toAddr(program, header.getFieldIdsOffset());
	int index = 0;
	for (FieldIDItem item : header.getFields()) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		DataType dataType = item.toDataType();
		createData(program, address, dataType);
		createFragment(program, "fields", address, address.add(dataType.getLength()));

		StringBuilder builder = new StringBuilder();
		builder.append("Field Index: 0x" + Integer.toHexString(index) + "\n");
		builder.append(
			"Class: " + DexUtil.convertTypeIndexToString(header, item.getClassIndex()) + "\n");
		builder.append(
			"Type: " + DexUtil.convertTypeIndexToString(header, item.getTypeIndex()) + "\n");
		builder.append("Name: " + DexUtil.convertToString(header, item.getNameIndex()) + "\n");
		setPlateComment(program, address, builder.toString());

		++index;

		address = address.add(dataType.getLength());
	}
}
 
Example 11
Source File: ThreadedTableModel.java    From ghidra with Apache License 2.0 5 votes vote down vote up
/**
 * Override this to change how filtering is performed.  This implementation will do nothing
 * if a <code>TableFilter</code> has not been set via a call to {@link #setTableFilter(TableFilter)}.
 * 
 *
 * @param data The list of data to be filtered.
 *
 * @param monitor the progress monitor to check for cancellation.
 * @param lastSortingContext the comparator used to sort data.  This can be used by overridden
 *                   filter methods that need to query data about how the table is sorted.
 * @return The <b>new</b> filtered list of data.  If no filtering takes place, then the
 * 	       original list should be returned.
 * @throws CancelledException If the filter operation is cancelled.
 */
protected List<ROW_OBJECT> doFilter(List<ROW_OBJECT> data,
		TableSortingContext<ROW_OBJECT> lastSortingContext, TaskMonitor monitor)
		throws CancelledException {

	// copy the filter so that it is not changed by another thread whilst this filter is
	// taking place

	if (data.size() == 0) {
		return data;
	}

	if (!hasFilter()) {
		return data;
	}

	monitor.initialize(data.size());

	TableFilter<ROW_OBJECT> filterCopy = getTableFilter();
	List<ROW_OBJECT> filteredList = new ArrayList<>();
	for (int row = 0; row < data.size(); row++) {
		if (monitor.isCancelled()) {
			return filteredList; // cancelled just return what has matches so far
		}

		ROW_OBJECT rowObject = data.get(row);
		if (filterCopy.acceptsRow(rowObject)) {
			filteredList.add(rowObject);
		}
		monitor.incrementProgress(1);
	}

	return filteredList;
}
 
Example 12
Source File: DyldCacheLocalSymbolsInfo.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void parseNList(MessageLog log, TaskMonitor monitor) throws CancelledException {
	FactoryBundledWithBinaryReader nListReader = new FactoryBundledWithBinaryReader(
		RethrowContinuesFactory.INSTANCE, reader.getByteProvider(), reader.isLittleEndian());
	monitor.setMessage("Parsing DYLD nlist symbol table...");
	monitor.initialize(nlistCount * 2);
	nListReader.setPointerIndex(startIndex + nlistOffset);
	try {

		for (int i = 0; i < nlistCount; ++i) {
			nlistList.add(NList.createNList(nListReader, is32bit));
			monitor.checkCanceled();
			monitor.incrementProgress(1);
		}
		// sort the entries by the index in the string table, so don't jump around reading
		List<NList> sortedList = nlistList
				.stream()
				.sorted((o1, o2) -> Integer.compare(o1.getStringTableIndex(),
					o2.getStringTableIndex()))
				.collect(Collectors.toList());

		// initialize the NList strings from string table
		long stringTableOffset = startIndex + stringsOffset;
		for (NList nList : sortedList) {
			monitor.checkCanceled();
			monitor.incrementProgress(1);
			nList.initString(nListReader, stringTableOffset);
		}
	}
	catch (IOException e) {
		log.appendMsg(DyldCacheAccelerateInfo.class.getSimpleName(), "Failed to parse nlist.");
	}
}
 
Example 13
Source File: ApplyMatchTask.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void applyMatches(TaskMonitor monitor) throws CancelledException {
	monitor.setMessage("Processing matches");
	monitor.initialize(matches.size());
	for (VTMatch match : matches) {
		monitor.checkCanceled();
		VTAssociation association = match.getAssociation();
		VTAssociationStatus status = association.getStatus();
		if (!status.canApply()) {
			continue;
		}

		acceptMatch(match);

		long progress = monitor.getProgress();
		MatchInfo matchInfo = controller.getMatchInfo(match);
		Collection<VTMarkupItem> markupItems = matchInfo.getAppliableMarkupItems(monitor);
		if (markupItems == null || markupItems.size() == 0) {
			monitor.incrementProgress(1);
			continue;
		}

		monitor.setMessage("Processing matches");
		monitor.setProgress(progress);

		applyMarkupItems(monitor, markupItems);
		monitor.incrementProgress(1);
	}

	monitor.setProgress(matches.size());
}
 
Example 14
Source File: FidProgramSeeker.java    From ghidra with Apache License 2.0 5 votes vote down vote up
/**
 * Searches the database for function names.
 * @param monitor a task monitor
 * @return the results of all the searching
 * @throws CancelledException if the user cancels
 */
public List<FidSearchResult> search(TaskMonitor monitor) throws CancelledException {
	List<FidSearchResult> result = new LinkedList<FidSearchResult>();

	FunctionManager functionManager = program.getFunctionManager();
	monitor.initialize(functionManager.getFunctionCount());
	FunctionIterator functions = functionManager.getFunctions(true);
	for (Function function : functions) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		try {
			HashFamily family = getFamily(function, monitor);
			if (family != null) {
				FidSearchResult searchResult = processMatches(function, family, monitor);
				if (searchResult != null) {
					result.add(searchResult);
				}
			}
		}
		catch (MemoryAccessException e) {
			Msg.showError(this, null, "Memory Access Exception",
				"Internal error, degenerate unhashable function");
		}
	}

	return result;
}
 
Example 15
Source File: ProgramMappingService.java    From ghidra with Apache License 2.0 4 votes vote down vote up
/**
 * Recursively searches the current active {@link Project} for {@link DomainFile}s that
 * have metadata that matches a {@link FSRL} in the specified list.
 * <p>
 * Warning, this operation is expensive and should only be done in a Task thread.
 * <p>
 * @param fsrls List of {@link FSRL} to match against the metadata of each DomainFile in Project.
 * @param monitor {@link TaskMonitor} to watch for cancel and update with progress.
 * @return Map of FSRLs to {@link DomainFile}s of the found files, never null.
 */
public static Map<FSRL, DomainFile> searchProjectForMatchingFiles(List<FSRL> fsrls,
		TaskMonitor monitor) {
	int fc = AppInfo.getActiveProject().getProjectData().getFileCount();
	if (fc > 0) {
		monitor.setShowProgressValue(true);
		monitor.setMaximum(fc);
		monitor.setProgress(0);
	}
	else {
		monitor.setIndeterminate(true);
	}
	monitor.setMessage("Searching project for matching files");

	Map<String, FSRL> fsrlsToFindByMD5;
	try {
		fsrlsToFindByMD5 = buildFullyQualifiedFSRLMap(fsrls, monitor);
	}
	catch (CancelledException ce) {
		Msg.info(ProgramMappingService.class, "Canceling project search");
		return Collections.emptyMap();
	}

	Map<FSRL, DomainFile> results = new HashMap<>();

	for (DomainFile domainFile : ProjectDataUtils.descendantFiles(
		AppInfo.getActiveProject().getProjectData().getRootFolder())) {
		if (monitor.isCancelled() || fsrlsToFindByMD5.isEmpty()) {
			break;
		}

		monitor.incrementProgress(1);
		Map<String, String> metadata = domainFile.getMetadata();

		FSRL dfFSRL = getFSRLFromMetadata(metadata, domainFile);
		if (dfFSRL != null) {
			// side effect: create association between the FSRL in the DomainFile's props
			// to the DomainFile's path if there is room in the cache.
			// (ie. don't blow out the cache for files that haven't been requested yet)
			createAssociation(dfFSRL, domainFile, true);
		}
		String dfMD5 = (dfFSRL != null) ? dfFSRL.getMD5() : getMD5FromMetadata(metadata);
		if (dfMD5 != null) {
			FSRL matchedFSRL = fsrlsToFindByMD5.get(dfMD5);
			if (matchedFSRL != null) {
				results.put(matchedFSRL, domainFile);
				fsrlsToFindByMD5.remove(dfMD5);
			}
		}
	}

	return results;
}
 
Example 16
Source File: DexHeaderFormatAnalyzer.java    From ghidra with Apache License 2.0 4 votes vote down vote up
private void processPrototypes(Program program, DexHeader header, TaskMonitor monitor,
		MessageLog log) throws Exception {
	monitor.setMessage("DEX: processing prototypes");
	monitor.setMaximum(header.getProtoIdsSize());
	monitor.setProgress(0);
	Address address = toAddr(program, header.getProtoIdsOffset());
	int index = 0;
	for (PrototypesIDItem item : header.getPrototypes()) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		DataType dataType = item.toDataType();
		createData(program, address, dataType);
		createFragment(program, "prototypes", address, address.add(dataType.getLength()));

		StringBuilder builder = new StringBuilder();
		builder.append("Prototype Index: 0x" + Integer.toHexString(index) + "\n");
		builder.append(
			"Shorty: " + DexUtil.convertToString(header, item.getShortyIndex()) + "\n");
		builder.append("Return Type: " +
			DexUtil.convertTypeIndexToString(header, item.getReturnTypeIndex()) + "\n");

		if (item.getParametersOffset() > 0) {
			builder.append("Parameters: " + "\n");
			TypeList parameters = item.getParameters();
			for (TypeItem parameter : parameters.getItems()) {
				monitor.checkCanceled();
				builder.append(
					DexUtil.convertTypeIndexToString(header, parameter.getType()) + " ");
			}

			DataType parametersDT = parameters.toDataType();
			Address parametersAddress = toAddr(program, item.getParametersOffset());
			createData(program, parametersAddress, parametersDT);
		}

		setPlateComment(program, address, builder.toString());

		++index;

		address = address.add(dataType.getLength());
	}
}
 
Example 17
Source File: ConstantPropagationAnalyzer.java    From ghidra with Apache License 2.0 4 votes vote down vote up
protected AddressSetView findLocations(Program program, AddressSetView set,
		Set<Address> locations, TaskMonitor monitor) throws CancelledException {

	monitor.setMessage("Finding function locations...");
	long total = set.getNumAddresses();
	monitor.initialize(total);

	// iterate over functions in program
	// add each defined function start to the list
	// return the address set that is minus the bodies of each function
	AddressSet inBodySet = new AddressSet();
	Iterator<Function> fiter = program.getFunctionManager().getFunctionsOverlapping(set);
	while (fiter.hasNext()) {
		monitor.checkCanceled();
		Function function = fiter.next();
		locations.add(function.getEntryPoint());
		inBodySet.add(function.getBody());
	}

	monitor.setProgress(total - inBodySet.getNumAddresses());
	set = set.subtract(inBodySet);

	// set now has Stuff in it that isn't in a recorded function body
	ReferenceManager referenceManager = program.getReferenceManager();
	AddressIterator referenceDestinationIterator =
		referenceManager.getReferenceDestinationIterator(set, true);

	AddressSet outOfBodySet = new AddressSet();
	while (referenceDestinationIterator.hasNext()) {
		monitor.checkCanceled();
		Address address = referenceDestinationIterator.next();
		ReferenceIterator referencesTo = referenceManager.getReferencesTo(address);
		while (referencesTo.hasNext()) {
			Reference reference = referencesTo.next();
			if (reference.getReferenceType().isCall()) {
				locations.add(address);
				outOfBodySet.add(address);
				// could subtract all local non-call flows from the set, but
				// might be extra work...
				break;
			}
		}
	}

	monitor.incrementProgress(outOfBodySet.getNumAddresses());
	set = set.subtract(outOfBodySet);

	// now iterate over individual address ranges, and use first address as a start
	outOfBodySet = new AddressSet();
	AddressRangeIterator addressRanges = set.getAddressRanges();
	while (addressRanges.hasNext()) {
		monitor.checkCanceled();
		AddressRange addressRange = addressRanges.next();
		locations.add(addressRange.getMinAddress());
		outOfBodySet.add(addressRange.getMinAddress());
	}

	monitor.incrementProgress(outOfBodySet.getNumAddresses());
	set = set.subtract(outOfBodySet);

	return set;
}
 
Example 18
Source File: AutoVersionTrackingCommand.java    From ghidra with Apache License 2.0 4 votes vote down vote up
/**
 * Runs the given version tracking (VT) correlator and applies the returned matches meeting the 
 * given score and confidence thresholds and are not otherwise blocked.
 * @param factory The correlator factory used to create and run the desired VT correlator.
 * @param options The options to pass the correlator including score and confidence values.
 * @param monitor Checks to see if user has cancelled.
 * @throws CancelledException
 */
private boolean correlateAndPossiblyApply(VTProgramCorrelatorFactory factory, VTOptions options,
		TaskMonitor monitor) throws CancelledException {

	monitor.checkCanceled();

	monitor.setMessage(
		"Finding and applying good " + factory.getName() + " matches and markup.");

	VTProgramCorrelator correlator = factory.createCorrelator(serviceProvider, sourceProgram,
		sourceAddressSet, destinationProgram, destinationAddressSet, options);

	VTMatchSet results = correlator.correlate(session, monitor);

	boolean hasMarkupErrors = applyMatches(results.getMatches(), correlator.getName(), monitor);

	monitor.incrementProgress(1);

	return hasMarkupErrors;

}
 
Example 19
Source File: SymbolMerger.java    From ghidra with Apache License 2.0 4 votes vote down vote up
private void processPrimaryChanges(TaskMonitor monitor) throws CancelledException {
	updateProgressMessage("Processing change of primary symbols...");
	monitor.setMessage("Symbol Merge: Processing change of primary symbols...");
	monitor.initialize(mySetPrimary.getNumAddresses());

	AddressIterator iter = mySetPrimary.getAddresses(true);
	while (iter.hasNext()) {
		monitor.incrementProgress(1);
		monitor.checkCanceled();
		incrementProgress(1);
		Address addr = iter.next();
		Symbol myPrimary = mySymTab.getPrimarySymbol(addr);
		if (myPrimary == null) {
			continue;
		}
		long myID = myPrimary.getID();
		int removeIndex = Arrays.binarySearch(latestRemoveIDs, myID);
		if (removeIndex >= 0) {
			Symbol originalSymbol = originalSymTab.getSymbol(myID);
			if (originalSymbol != null) {
				saveRemoveConflict(originalSymbol);
			}
		}
		if (latestSetPrimary.contains(addr)) {
			// Both changed primary so check for conflict.
			Symbol latestPrimary = latestSymTab.getPrimarySymbol(addr);
			Symbol latestSameAsMy = SimpleDiffUtility.getSymbol(myPrimary, latestPgm);
			if (!same(latestPrimary, latestSameAsMy)) {
				savePrimaryConflict(addr);
			}
		}
		else {
			// Only MY changed primary so try to set it.
			// THe symbol may not have been added yet and will get set later on add.
			Symbol resultSym = getResultSymbolFromMySymbol(myPrimary);
			if (resultSym != null) {
				resultSym.setPrimary();
			}
		}
	}
}
 
Example 20
Source File: MatchData.java    From ghidra with Apache License 2.0 4 votes vote down vote up
private static void generateMatches(List<MatchedData> result, Program aProgram,
		Program bProgram,
		List<SearchResult<Address, Pair<Set<Address>, Set<Address>>>> searchResults,
		int alignment, boolean includeOneToOne, boolean includeNonOneToOne, TaskMonitor monitor)
		throws CancelledException {

	HashSet<ByteTrieNodeIfc<Pair<Set<Address>, Set<Address>>>> done =
		new HashSet<ByteTrieNodeIfc<Pair<Set<Address>, Set<Address>>>>();
	Listing aListing = aProgram.getListing();
	Listing bListing = bProgram.getListing();

	monitor.initialize(searchResults.size());
	monitor.setMessage("(4 of 4) Create match objects");
	for (SearchResult<Address, Pair<Set<Address>, Set<Address>>> searchResult : searchResults) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		ByteTrieNodeIfc<Pair<Set<Address>, Set<Address>>> node = searchResult.getNode();
		if (!done.contains(node)) {
			Pair<Set<Address>, Set<Address>> pair = searchResult.getItem();
			Set<Address> aLocations = pair.first;
			Set<Address> bLocations = pair.second;
			final int aSize = aLocations.size();
			final int bSize = bLocations.size();

			boolean processResult =
				(includeOneToOne && aSize == 1 && bSize == 1) ||
					(includeNonOneToOne && (aSize > 1 || bSize > 1));

			if (processResult) {
				for (Address aLocation : aLocations) {
					for (Address bLocation : bLocations) {
						Data aDatum = aListing.getDataAt(aLocation);
						Data bDatum = bListing.getDataAt(bLocation);
						MatchedData matchedData =
							new MatchedData(aProgram, bProgram, aLocation, bLocation, aDatum,
								bDatum, aSize, bSize, null);
						result.add(matchedData);
					}
				}
			}
			done.add(node);
		}
	}
}