private void accumulateFunctionReferences(int depth, Set<Function> list, Program program,
			Address address) {

		if (depth >= MAX_DEPTH) {
			return;
		}

		/*
		 * If address corresponds to a Thunk Function, in addition to following back references,
		 * you should collect back-thunk-addresses (not included in references) by using the
		 * method Function.getFunctionThunkAddresses (Elf programs can have thunks which do
		 * not have a forward reference but thunk another function).  You may also need to dedup
		 * your list of functions returned if this could cause fallout.  In addition, you may
		 * need to watch out for recursion loops which could occur (i.e., a function pointer which
		 * has a secondary reference to itself - contrived example).
		 */

		FunctionManager functionManager = program.getFunctionManager();
		Function addressFunction = functionManager.getFunctionAt(address);
		if (addressFunction != null) {
			Address[] thunkAddresses = addressFunction.getFunctionThunkAddresses();
			if (thunkAddresses != null) {
				for (Address thunkAddress : thunkAddresses) {
					accumulateFunctionReferences(depth + 1, list, program, thunkAddress);
				}
			}
		}

		// Handle References to the address
		if (address.isStackAddress() || address.isRegisterAddress()) {
			return; // can't have references to these types of addresses
		}

		ReferenceManager refManager = program.getReferenceManager();
		Listing listing = program.getListing();
		ReferenceIterator it = refManager.getReferencesTo(address);
		while (it.hasNext()) {
			Reference reference = it.next();
			Address fromAddress = reference.getFromAddress();
			CodeUnit codeUnit = listing.getCodeUnitAt(fromAddress);

			// if the code unit at the location of the reference is an Instruction, then get the
			// function where the reference occurs and determine if it passes the basic VT function
			// match test set above
			if (codeUnit instanceof Instruction) {
				Function function = functionManager.getFunctionContaining(fromAddress);
				if (function == null) {
					continue;
				}

				if (function.isThunk()) {
					// also add references to the thunk function
					Address entryPoint = function.getEntryPoint();
					accumulateFunctionReferences(depth + 1, list, program, entryPoint);
				}
				else {
					list.add(function);
				}
			}
			else if (codeUnit instanceof Data) {
				accumulateFunctionReferences(depth + 1, list, program, fromAddress);
			}
		}
	}
Recursively traces the reference chains from a given address and returns by reference a
list of functions found along the reference chain.

@param depth the initial recursion depth
@param list a function accumulation list that is updated by this function
@param program the program
@param address an address represents a location in a program
Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/correlator/program/VTAbstractReferenceProgramCorrelator.java