private void replaceFunctionSymbol(Address fromEntryPoint, Address toEntryPoint,
			LongLongHashtable conflictSymbolIDMap, TaskMonitor monitor)
			throws DuplicateNameException, InvalidInputException {
		// Assumes: The function in the destination program should already be replaced at this point.
		// However, the symbol name and name space have not been replaced.
		FunctionManager fromFunctionMgr = fromProgram.getFunctionManager();
		FunctionManager toFunctionMgr = toProgram.getFunctionManager();
		Function fromFunc = fromFunctionMgr.getFunctionAt(fromEntryPoint);
		Function toFunc = toFunctionMgr.getFunctionAt(toEntryPoint);
		if (fromFunc == null) {
			return;
		}

		Symbol fromSymbol = fromFunc.getSymbol();
		SourceType fromSource = fromSymbol.getSource();
		boolean isFromDefaultThunk = FunctionMerge.isDefaultThunk(fromFunc);
		String fromName = fromSymbol.getName();
		Namespace fromNamespace = // default thunks will lie about their namespace
			isFromDefaultThunk ? fromProgram.getGlobalNamespace() : fromSymbol.getParentNamespace();

		Symbol toSymbol;
		if (toFunc == null) {
			if (fromSource == SourceType.DEFAULT) {
				return;
			}
			Namespace toNamespace = toProgram.getGlobalNamespace();
			toFunc = toFunctionMgr.getFunctionContaining(toEntryPoint);
			if (toFunc != null) {
				toNamespace = toFunc;
			}
			// If replacing a function name, but there isn't a function in the destination,
			// create a regular label with the function name unless its the default name.
			toSymbol = toSymbolTable.createLabel(toEntryPoint, fromName, toNamespace, fromSource);
		}
		else {
			toSymbol = toFunc.getSymbol();

			// Replacing the function name.
			if (toSymbol.equals(fromSymbol)) {
				if (fromSource != SourceType.DEFAULT && toSymbol.getSource() != fromSource) {
					try {
						toSymbol.setSource(fromSource);
					}
					catch (IllegalArgumentException e) {
						Msg.warn(this, e.getMessage());
					}
				}
				boolean pinned = fromSymbol.isPinned();
				if (toSymbol.isPinned() != pinned) {
					toSymbol.setPinned(pinned);
				}
				return; // Symbols aren't different.
			}

			Namespace newToNamespace = resolveNamespace(fromNamespace, conflictSymbolIDMap);
			try {
				toFunc.setParentNamespace(newToNamespace);
			}
			catch (CircularDependencyException | InvalidInputException e) {
				Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
			}

			String toName = toSymbol.getName();
			if (toSymbol.getSource() != fromSource || !toName.equals(fromName)) {
				toFunc.setName(fromName, fromSource);
			}
		}

		boolean pinned = fromSymbol.isPinned();
		if (toSymbol.isPinned() != pinned) {
			toSymbol.setPinned(pinned);
		}
	}
Replaces the function symbol at the indicated entry point in the "to" program with the
function symbol in the "from" program. If there is no function in the "to" program the
symbol becomes a regular "label" symbol.
@param fromEntryPoint the entry point address
This address should be derived from the "from" program.
@param conflictSymbolIDMap maps the symbol IDs in the "from" program to the symbol IDs
in the "to" program for any symbols (and their associated objects) that were created
with conflict names.
(key = "from" program's symbol ID; value = "to" program's symbol ID)
@param monitor the task monitor for notifying the user of this merge's progress.

@throws InvalidInputException if the function symbol name from the second program isn't valid
@throws DuplicateNameException if a duplicate name is encountered that couldn't be handled
while replacing the function symbol.
Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolMerge.java