private void followToParam(HashMap<Address, Long> constUse, ArrayList<PcodeOp> defUseList,
			HighFunction highFunction, Varnode vnode, ArrayList<FunctionParamUse> funcList,
			HashSet<SequenceNumber> doneSet) {

		// follow back up through
		PcodeOp def = vnode.getDef();
		Function function = highFunction.getFunction();
		if (def == null) {
			HighVariable hvar = vnode.getHigh();
			if (hvar instanceof HighParam) {
				funcList.add(new FunctionParamUse(function.getName(), function.getEntryPoint(),
					((HighParam) hvar).getSlot(), hvar.getRepresentative(), defUseList));
				return;
			}
			if (hvar instanceof HighGlobal) {
				followThroughGlobal(constUse, defUseList, hvar, funcList, doneSet);
			}
			return;
		}

		// have we done this vnode source already?
		Address funcEntry = function.getEntryPoint();
		SequenceNumber seqNum = def.getSeqnum();
		remapAddress(funcEntry, def.getOutput().getPCAddress());

		if (doneSet == null) {
			doneSet = new HashSet<SequenceNumber>();
		}
		if (seqNum != null && doneSet.contains(seqNum)) {
			return;
		}
		doneSet.add(seqNum);

		int opcode = def.getOpcode();
		switch (opcode) {
			case PcodeOp.COPY:
				if (def.getInput(0).isConstant()) {
					long value = def.getInput(0).getOffset();
					try {
						value = applyDefUseList(value, defUseList);
						constUse.put(remapAddress(funcEntry, def.getOutput().getPCAddress()),
							value);
						println("   " + function.getName() + "    " +
							def.getOutput().getPCAddress() + " : 0x" + Long.toHexString(value));
					}
					catch (InvalidInputException exc) {
						// Do nothing
					}
					return;
				}
				followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
					doneSet);
				return;
			case PcodeOp.LOAD:
				if (def.getInput(0).isConstant() && def.getInput(1).isConstant()) {
					long space = def.getInput(0).getOffset();
					long offset = def.getInput(1).getOffset();
					if (space != funcEntry.getAddressSpace().getSpaceID()) {
						break;
					}
					try {
						offset = applyDefUseList(offset, defUseList);
						constUse.put(remapAddress(funcEntry, def.getOutput().getPCAddress()),
							offset);
						println("   " + function.getName() + "    " +
							def.getOutput().getPCAddress() + " : 0x" + Long.toHexString(offset));
					}
					catch (InvalidInputException exc) {
						// Do nothing
					}
					return;
				}
				followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
					doneSet);
				return;
			case PcodeOp.INT_ZEXT:
				followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
					doneSet);
				return;
			case PcodeOp.MULTIEQUAL:
				for (int i = 0; i < def.getNumInputs(); i++) {
					ArrayList<PcodeOp> splitUseList = new ArrayList<>(defUseList);
					followToParam(constUse, splitUseList, highFunction, def.getInput(i), funcList,
						doneSet);
				}
				return;
			case PcodeOp.CAST:
				followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
					doneSet);
				return;
			case PcodeOp.INDIRECT:
				Varnode output = def.getOutput();
				if (output.getAddress().equals(def.getInput(0).getAddress())) {
					followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
						doneSet);
					return;
				}
				if (def.getInput(0).isUnique()) {
					followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
						doneSet);
					return;
				}
				break;
			case PcodeOp.INT_AND:
				if (def.getInput(1).isConstant()) {
					defUseList.add(0, def);
					followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
						doneSet);
					return;
				}
				break;
			case PcodeOp.INT_ADD:
				if (def.getInput(1).isConstant()) {
					defUseList.add(0, def);
					followToParam(constUse, defUseList, highFunction, def.getInput(0), funcList,
						doneSet);
					return;
				}
				if (vnode.getHigh() instanceof HighParam) {
					// Do nothing
				}
				break;
			case PcodeOp.PTRADD: // Pointer + some offset (usually an array access)
				// if (!def.getInput(1).isConstant() ||
				// !def.getInput(2).isConstant()) {
				// break;
				// }
				// DataType outDt = def.getOutput().getHigh().getDataType();
				// println ("        type = " + outDt.getName());
				// long value = getSigned(def.getInput(1)) *
				// def.getInput(2).getOffset();
				//
				// try {
				// value = applyDefUseList(value, defUseList);
				// constUse.put(def.getOutput().getPCAddress(), value);
				// } catch (InvalidInputException exc) {}
				break;

			case PcodeOp.PTRSUB: // Pointer + some sub element access (usually a
								// structure ref)
				Varnode offsetVal = def.getInput(1);
				if (!offsetVal.isConstant()) {
					break;
				}
				Varnode baseVal = def.getInput(0);
				if (baseVal.isConstant()) {
					// both constant, just use it and return the address
					long value = baseVal.getOffset() + offsetVal.getOffset();
					try {
						value = applyDefUseList(value, defUseList);
						constUse.put(remapAddress(funcEntry, def.getOutput().getPCAddress()),
							value);
						println("   " + function.getName() + "    " +
							def.getOutput().getPCAddress() + " : 0x" + Long.toHexString(value));
					}
					catch (InvalidInputException exc) {
						// Do nothing
					}
					return;
				}
				// TODO: handle access into data structure
				// DataType inDt = def.getInput(0).getHigh().getDataType();
				// DataType subDt = def.getOutput().getHigh().getDataType();
				// println ("        type = " + subDt.getName());
				// long subOff = getSigned(def.getInput(1));
				// outDt = subDt;
				// if (subDt instanceof Pointer) {
				// outDt = ((Pointer) subDt).getDataType();
				// if (outDt == null) {
				// }
				// }
				// try {
				// subOff = applyDefUseList(subOff, defUseList);
				// constUse.put(def.getOutput().getPCAddress(), subOff);
				// } catch (InvalidInputException exc) {}
				break;
		}

		constUse.put(remapAddress(funcEntry, vnode.getPCAddress()), null);
		println("   " + function.getName() + "    " + vnode.getPCAddress() + " : Lost");
		// println("     Lost IT! " + vnode.getPCAddress());
	}
Backtrack to a constant given a start position of a parameter of a given
function Useful if you want to start from a function paramter.

@param f function to start in
@param paramIndex parameter index to backtrack from
@param tableChooserDialog accumulate entries. Don't like passing it, but this way the
        user gets immediate feedback as locations are found
@return a map of Addresses to constants (constants could be NULL)
@throws CancelledException if cancelled
Ghidra/Features/Decompiler/ghidra_scripts/ShowConstantUse.java