@Override
	public CompletableFuture<Void> writeRegisterAsync(TracePlatform platform, TraceThread thread,
			int frameLevel, RegisterValue value) {
		MatchedMethod writeReg =
			matches.getBest(WriteRegMatcher.class, null, ActionName.WRITE_REG, WriteRegMatcher.ALL);
		if (writeReg == null) {
			return AsyncUtils.nil();
		}
		if (!(thread instanceof TraceObjectThread tot)) {
			Msg.error(this, "Non-object trace with TraceRmi!");
			return AsyncUtils.nil();
		}
		FoundRegister found = findRegister(tot, frameLevel, value.getRegister());
		if (found == null) {
			Msg.warn(this, "Could not find register " + value.getRegister() + " in object model.");
		}
		else if (found.register != value.getRegister()) {
			value = retrieveAndCombine(platform, thread, frameLevel, found, value);
		}

		RemoteParameter paramThread = writeReg.params.get("thread");
		if (paramThread != null) {
			return writeReg.method.invokeAsync(Map.ofEntries(
				Map.entry(paramThread.name(), tot.getObject()),
				Map.entry(writeReg.params.get("name").name(), found.name()),
				Map.entry(writeReg.params.get("value").name(), getBytes(value))))
					.toCompletableFuture()
					.thenApply(__ -> null);
		}

		RemoteParameter paramFrame = writeReg.params.get("frame");
		if (paramFrame != null) {
			TraceStack stack = trace.getStackManager().getLatestStack(thread, getSnap());
			TraceStackFrame frame = stack.getFrame(getSnap(), frameLevel, false);
			if (!(frame instanceof TraceObjectStackFrame tof)) {
				Msg.error(this, "Non-object trace with TraceRmi!");
				return AsyncUtils.nil();
			}
			return writeReg.method.invokeAsync(Map.ofEntries(
				Map.entry(paramFrame.name(), tof.getObject()),
				Map.entry(writeReg.params.get("name").name(), found.name()),
				Map.entry(writeReg.params.get("value").name(), getBytes(value))))
					.toCompletableFuture()
					.thenApply(__ -> null);
		}
		if (found == null || !found.value.isObject()) {
			return AsyncUtils.nil();
		}
		return writeReg.method.invokeAsync(Map.ofEntries(
			Map.entry(writeReg.params.get("register").name(), found.value.getChild()),
			Map.entry(writeReg.params.get("value").name(), getBytes(value))))
				.toCompletableFuture()
				.thenApply(__ -> null);
	}
When checking for register validity, we consider it valid if it or any of its parents are
valid, or any alias thereof.
Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java