@Override
	public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
			throws CancelledException {

		SequenceSearchState root = initialize(program);
		if (root == null) {
			String message = "Could not initialize a search state.";
			log.appendMsg(getName(), message);
			log.setStatus(message);

			return false;
		}

		boolean doExecutableBlocksOnly = checkForExecuteBlock(program) && executableBlocksOnly;

		// clear out any previous potential matches, because we are re-looking at these places
		//   this will keep cruft from accumulating in the property map.
		getOrCreatePotentialMatchPropertyMap(program).remove(set);

		MemoryBytePatternSearcher patternSearcher;
		patternSearcher = new MemoryBytePatternSearcher("Function Starts", root) {

			@Override
			public void preMatchApply(MatchAction[] actions, Address addr) {
				contextValueList = null; // make sure, only context from these actions used
			}

			@Override
			public void postMatchApply(MatchAction[] actions, Address addr) {
				// Actions might have set context, check if postcondition failed first
				if (!postreqFailedResult.contains(addr)) {
					setCurrentContext(program, addr);
				}
				// get rid of the context list.
				contextValueList = null;
			}
		};
		patternSearcher.setSearchExecutableOnly(doExecutableBlocksOnly);

		patternSearcher.search(program, set, monitor);

		AutoAnalysisManager analysisManager = AutoAnalysisManager.getAnalysisManager(program);
		if (!disassemResult.isEmpty()) {
			analysisManager.disassemble(disassemResult, AnalysisPriority.DISASSEMBLY);
		}
		analysisManager.setProtectedLocations(codeLocations);

		if (!potentialFuncResult.isEmpty()) {
			// could be a pattern that said this is a function start, so it isn't potentially anymore
			potentialFuncResult = potentialFuncResult.subtract(funcResult);

			// kick off a later analyzer to create the functions after all the fallout from disassemlby
			PossibleDelayedFunctionCreator analyzer = new PossibleDelayedFunctionCreator();
			analysisManager.scheduleOneTimeAnalysis(analyzer, potentialFuncResult);
		}

		if (!funcResult.isEmpty()) {
			// pattern said this is a functions start, kick of creation later
			analysisManager.createFunction(funcResult, false);
		}
		return true;
	}
Get an existing function right above the addr.
@param program program to check
@param addr address to check
@return true if there is an existing function above addr
Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java