@Override
	public Variable getReferencedVariable(Address instrAddr, Address storageAddr, int size,
			boolean isRead) {

		// TODO: Add caching !!!

		lock.acquire();
		try {
			Function func = getFunctionContaining(instrAddr);
			if (func == null) {
				return null;
			}

			Variable[] variables = func.getAllVariables();

			Parameter paramCandidate = null;
			List<Variable> localCandidates = null;
			Variable firstCandidate = null;

			if (size <= 0) {
				size = 1;
			}
			Register register = program.getRegister(storageAddr, size);

			for (Variable var : variables) {

				VariableStorage variableStorage = var.getVariableStorage();

				// since we do not have size - assume any intersection with a register is a match
				if ((register != null && variableStorage.intersects(register)) ||
					(register == null && var.getVariableStorage().contains(storageAddr))) {

					if (var instanceof Parameter) {
						paramCandidate = (Parameter) var;
					}
					else if (firstCandidate != null) {
						if (localCandidates == null) {
							localCandidates = new ArrayList<>();
							localCandidates.add(firstCandidate);
						}
						localCandidates.add(var);
					}
					else {
						firstCandidate = var;
					}
				}
			}

			int useOffset = (int) instrAddr.subtract(func.getEntryPoint());
			if (isRead) {
				if (useOffset == 0) {
					return paramCandidate;
				}
				--useOffset; // read use must be in-scope prior to the use instruction
			}
			if (useOffset < 0) {
				// shift negative offsets
				useOffset = Integer.MAX_VALUE - useOffset;
			}

			if (localCandidates == null) {
				// Check single candidate
				if (firstCandidate != null) {
					int varFirstUse = firstCandidate.getFirstUseOffset();
					if (varFirstUse < 0) {
						varFirstUse = Integer.MAX_VALUE - varFirstUse;
					}
					if (varFirstUse <= useOffset) {
						return firstCandidate;
					}
				}
				return paramCandidate;
			}

			// Examine each candidate variable in list
			Variable bestVar = null;
			int bestFirstUse = 0;
			for (Variable var : localCandidates) {
				int varFirstUse = var.getFirstUseOffset();
				if (varFirstUse < 0) {
					varFirstUse = Integer.MAX_VALUE - varFirstUse;
				}
				if (varFirstUse <= useOffset && (bestVar == null || bestFirstUse < varFirstUse)) {
					bestVar = var;
					bestFirstUse = varFirstUse;
				}
			}
			if (bestVar == null) {
				bestVar = paramCandidate;
			}
			return bestVar;
		}
		finally {
			lock.release();
		}
	}
Remove variable references in the given address set.
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionManagerDB.java