rem: {  thread_id threadID = message.run_thread.thread; uint32 handleEvent = message.run_thread.handle_event;  TRACE(("nub thread %ld: B_DEBUG_MESSAGE_RUN_THREAD: "
add: case B_DEBUG_MESSAGE_STEP_THREAD: {  thread_id threadID; uint32 handleEvent; bool singleStep;  if (command == B_DEBUG_MESSAGE_RUN_THREAD) { threadID = message.run_thread.thread; handleEvent = message.run_thread.handle_event; singleStep = false; } else { threadID = message.step_thread.thread; handleEvent = message.step_thread.handle_event; singleStep = true; }  TRACE(("nub thread %ld: B_DEBUG_MESSAGE_%s_THREAD: "
context: debug_nub_thread(void *){	// check, if we're still the current nub thread and get our port	cpu_status state = disable_interrupts();	GRAB_TEAM_LOCK();	struct thread *nubThread = thread_get_current_thread();	if (nubThread->team->debug_info.nub_thread != nubThread->id)		return 0;	port_id port = nubThread->team->debug_info.nub_port;	RELEASE_TEAM_LOCK();	restore_interrupts(state);	TRACE(("debug_nub_thread() thread: %ld, team %ld, nub port: %ld\n",		nubThread->id, nubThread->team->id, port));	// command processing loop	while (true) {		int32 command;		debug_nub_message_data message;		ssize_t messageSize = kill_interruptable_read_port(port, &command,			&message, sizeof(message));		if (messageSize < 0) {			// The port is not longer valid or we were interrupted by a kill			// signal: If we are still listed in the team's debug info as nub			// thread, we need to update that.			nub_thread_cleanup(nubThread);			TRACE(("nub thread %ld: terminating: %lx\n", nubThread->id,				messageSize));			return messageSize;		}		bool sendReply = false;		union {			debug_nub_read_memory_reply		read_memory;			debug_nub_write_memory_reply	write_memory;		} reply;		int32 replySize = 0;		port_id replyPort = -1;		// process the command		switch (command) {			case B_DEBUG_MESSAGE_READ_MEMORY:			{				// get the parameters				replyPort = message.read_memory.reply_port;				void *address = message.read_memory.address;				int32 size = message.read_memory.size;				status_t result = B_OK;				// check the parameters				if (!IS_USER_ADDRESS(address))					result = B_BAD_ADDRESS;				else if (size <= 0 || size > B_MAX_READ_WRITE_MEMORY_SIZE)					result = B_BAD_VALUE;				// read the memory				if (result == B_OK)					result = user_memcpy(reply.read_memory.data, address, size);				reply.read_memory.error = result;				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_READ_MEMORY: "					"reply port: %ld, address: %p, size: %ld, result: %lx\n",					nubThread->id, replyPort, address, size, result));				// send only as much data as necessary				int32 bytesRead = (result == B_OK ? size : 0);				replySize = reply.read_memory.data + bytesRead - (char*)&reply;				sendReply = true;				break;			}			case B_DEBUG_MESSAGE_WRITE_MEMORY:			{				// get the parameters				replyPort = message.write_memory.reply_port;				void *address = message.write_memory.address;				int32 size = message.write_memory.size;				const char *data = message.write_memory.data;				int32 realSize = (char*)&message + messageSize - data;				status_t result = B_OK;				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_WRITE_MEMORY: "					"reply port: %ld, address: %p, size: %ld\n", nubThread->id,					replyPort, address, size));				// check the parameters				if (!IS_USER_ADDRESS(address))					result = B_BAD_ADDRESS;				else if (size <= 0 || size > realSize)					result = B_BAD_VALUE;				// write the memory				if (result == B_OK)					result = user_memcpy(address, data, size);				reply.write_memory.error = result;				sendReply = true;				replySize = sizeof(debug_nub_write_memory_reply);				break;			}			case B_DEBUG_MESSAGE_SET_TEAM_FLAGS:			{				// get the parameters				int32 flags = message.set_team_flags.flags					& B_TEAM_DEBUG_USER_FLAG_MASK;				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_TEAM_FLAGS: "					"flags: %lx\n", nubThread->id, flags));				struct team *team = thread_get_current_thread()->team;				// set the flags				cpu_status state = disable_interrupts();				GRAB_TEAM_LOCK();				flags |= team->debug_info.flags & B_TEAM_DEBUG_KERNEL_FLAG_MASK;				atomic_set(&team->debug_info.flags, flags);				RELEASE_TEAM_LOCK();				restore_interrupts(state);				break;			}			case B_DEBUG_MESSAGE_SET_THREAD_FLAGS:			{				// get the parameters				thread_id threadID = message.set_thread_flags.thread;				int32 flags = message.set_thread_flags.flags					& B_THREAD_DEBUG_USER_FLAG_MASK;				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_THREAD_FLAGS: "					"thread: %ld, flags: %lx\n", nubThread->id, threadID,					flags));				// set the flags				cpu_status state = disable_interrupts();				GRAB_THREAD_LOCK();				struct thread *thread					= thread_get_thread_struct_locked(threadID);				if (thread->team == thread_get_current_thread()->team) {					flags |= thread->debug_info.flags						& B_THREAD_DEBUG_KERNEL_FLAG_MASK;					atomic_set(&thread->debug_info.flags, flags);				}				RELEASE_THREAD_LOCK();				restore_interrupts(state);				break;			}			case B_DEBUG_MESSAGE_RUN_THREAD:			{				// get the parameters				thread_id threadID = message.run_thread.thread;				uint32 handleEvent = message.run_thread.handle_event;				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_RUN_THREAD: "					"thread: %ld, handle event: %lu\n", nubThread->id,					threadID, handleEvent));				// find the thread and get its debug port				state = disable_interrupts();				GRAB_THREAD_LOCK();				port_id threadDebugPort = -1;				struct thread *thread					= thread_get_thread_struct_locked(threadID);				if (thread && thread->team == nubThread->team					&& thread->debug_info.flags & B_THREAD_DEBUG_STOPPED) {					threadDebugPort = thread->debug_info.debug_port;				}				RELEASE_THREAD_LOCK();				restore_interrupts(state);				// send a message to the debugged thread				if (threadDebugPort >= 0) {					debugged_thread_run commandMessage;					commandMessage.handle_event = handleEvent;					write_port(threadDebugPort,						B_DEBUGGED_THREAD_MESSAGE_CONTINUE, &commandMessage,						sizeof(commandMessage));				}				break;			}			case B_DEBUG_MESSAGE_GET_WHY_STOPPED:			{				// get the parameters				thread_id threadID = message.get_why_stopped.thread;				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_WHY_STOPPED: "					"thread: %ld\n", nubThread->id, threadID));				// find the thread and get its debug port				state = disable_interrupts();				GRAB_THREAD_LOCK();				port_id threadDebugPort = -1;				struct thread *thread					= thread_get_thread_struct_locked(threadID);				if (thread && thread->team == nubThread->team					&& thread->debug_info.flags & B_THREAD_DEBUG_STOPPED) {					threadDebugPort = thread->debug_info.debug_port;				}				RELEASE_THREAD_LOCK();				restore_interrupts(state);				// send a message to the debugged thread				if (threadDebugPort >= 0) {					write_port(threadDebugPort,						B_DEBUGGED_THREAD_GET_WHY_STOPPED, NULL, 0);				}				break;			}		}		// send the reply, if necessary		if (sendReply) {			status_t error = kill_interruptable_write_port(replyPort, command,				&reply, replySize);			if (error != B_OK) {				// The debugger port is either not longer existing or we got				// interrupted by a kill signal. In either case we terminate.				nub_thread_cleanup(nubThread);				return error;			}		}	}}