@Override
	public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
			throws CancelledException {
		if (!fromAddr.isMemoryAddress() || !toAddr.isMemoryAddress()) {
			throw new IllegalArgumentException(
				"moveAddressRange only supported for memory addresses");
		}
		if (fromAddr.equals(toAddr)) {
			return;
		}
		Set<Address> primaryFixups = new HashSet<>();
		lock.acquire();
		try {
			invalidateCache(true);
			Address lastAddress = fromAddr.add(length - 1);
			AddressRange range = new AddressRangeImpl(fromAddr, lastAddress);

			// in order to handle overlapping ranges, need to iterate in the correct direction
			SymbolIterator symbolIterator =
				(fromAddr.compareTo(toAddr) > 0) ? getSymbolIterator(fromAddr, true)
						: getSymbolIterator(lastAddress, false);

			for (Symbol symbol : symbolIterator) {
				if (!range.contains(symbol.getAddress())) {
					break;
				}
				if (!(symbol instanceof MemorySymbol memSym)) {
					throw new AssertionError(
						"Unexpected symbol type within memory range: " + symbol.getClass());
				}
				Address newAddress = toAddr.add(memSym.getAddress().subtract(fromAddr));

				// any address that has symbols added or removed may have a corrupted primary
				// (too many or non-existent)
				primaryFixups.add(memSym.getAddress());
				primaryFixups.add(newAddress);

				moveSymbolForMemoryBlockMove(memSym, newAddress);
			}
			// go back and make sure there is a valid primary symbol at touched addresses
			fixupPrimarySymbols(primaryFixups);
		}
		finally {
			lock.release();
		}
	}
Called by the NamespaceManager when a namespace is removed; remove all symbols that have the
given namespace ID.

@param namespaceID ID of namespace being removed
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java