public static List<MatchedFunctions> matchOneFunction(Program aProgram, Address aEntryPoint,
			Program bProgram, AddressSetView bAddressSet, FunctionHasher hasher,
			TaskMonitor monitor)
			throws CancelledException {
		Map<Long, Match> functionHashes = new HashMap<>();
		List<MatchedFunctions> functionMatches = new ArrayList<MatchedFunctions>();

		Function aFunc = aProgram.getFunctionManager().getFunctionContaining(aEntryPoint);
		FunctionIterator bProgfIter =
			bAddressSet == null ? bProgram.getFunctionManager().getFunctions(true)
					: bProgram.getFunctionManager().getFunctions(bAddressSet, true);

		// Hash the one function in program A

		hashFunction(monitor, functionHashes, aFunc, hasher, true);

		// Hash functions in Program B
		while (!monitor.isCancelled() && bProgfIter.hasNext()) {
			Function func = bProgfIter.next();
			hashFunction(monitor, functionHashes, func, hasher, false);
		}

		//Find the remaining hash matches ---> unique code match left and THERE is no symbol that matches
		//in the other program.
		List<Long> keys = new ArrayList<>(functionHashes.keySet());
		for (long key : keys) {
			if (monitor.isCancelled()) {
				break;
			}
			Match match = functionHashes.get(key);
			ArrayList<Address> aProgAddrs = match.aAddresses;
			ArrayList<Address> bProgAddrs = match.bAddresses;

			// Want all possible matches from destination program
			if ((aProgAddrs.size() == 1) && (bProgAddrs.size() >= 1)) {
				for (int m = 0; m < bProgAddrs.size(); m++) {
					MatchedFunctions functionMatch =
						new MatchedFunctions(aProgram, bProgram, aProgAddrs.get(0),
							bProgAddrs.get(m), aProgAddrs.size(), bProgAddrs.size(),
							"Code Only Match");
					functionMatches.add(functionMatch);
				}
				functionHashes.remove(key);
			}
		}

		return functionMatches;
	}
This class does the work of matching subroutines. Every subroutine
in the current program is hashed and the start address is put into a 
table. There are often identical subroutines which may have the same hash
value. Then the subroutines in the other program are hashed as well. All unique
match pairs are returned as matches. The next step would be to use call graph
information or address order to get additional matches.
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchFunctions.java