xref: /haiku/src/system/kernel/debug/user_debugger.cpp (revision fef6144999c2fa611f59ee6ffe6dd7999501385c)
1 /*
2  * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include <debugger.h>
11 #include <kernel.h>
12 #include <KernelExport.h>
13 #include <ksignal.h>
14 #include <ksyscalls.h>
15 #include <sem.h>
16 #include <team.h>
17 #include <thread.h>
18 #include <thread_types.h>
19 #include <user_debugger.h>
20 #include <vm.h>
21 #include <vm_types.h>
22 #include <arch/user_debugger.h>
23 
24 //#define TRACE_USER_DEBUGGER
25 #ifdef TRACE_USER_DEBUGGER
26 #	define TRACE(x) dprintf x
27 #else
28 #	define TRACE(x) ;
29 #endif
30 
31 
32 static port_id sDefaultDebuggerPort = -1;
33 	// accessed atomically
34 
35 
36 static status_t ensure_debugger_installed(team_id teamID, port_id *port = NULL);
37 static void get_team_debug_info(team_debug_info &teamDebugInfo);
38 
39 
40 static ssize_t
41 kill_interruptable_read_port(port_id port, int32 *code, void *buffer,
42 	size_t bufferSize)
43 {
44 	return read_port_etc(port, code, buffer, bufferSize,
45 		B_KILL_CAN_INTERRUPT, 0);
46 }
47 
48 
49 static status_t
50 kill_interruptable_write_port(port_id port, int32 code, const void *buffer,
51 	size_t bufferSize)
52 {
53 	return write_port_etc(port, code, buffer, bufferSize,
54 		B_KILL_CAN_INTERRUPT, 0);
55 }
56 
57 
58 static status_t
59 debugger_write(port_id port, int32 code, const void *buffer, size_t bufferSize,
60 	bool dontWait)
61 {
62 	TRACE(("debugger_write(): thread: %ld, team %ld, port: %ld, code: %lx, message: %p, "
63 		"size: %lu, dontWait: %d\n", thread_get_current_thread()->id,
64 		thread_get_current_thread()->team->id, port, code, buffer, bufferSize,
65 		dontWait));
66 
67 	status_t error = B_OK;
68 
69 	// get the team debug info
70 	team_debug_info teamDebugInfo;
71 	get_team_debug_info(teamDebugInfo);
72 	sem_id writeLock = teamDebugInfo.debugger_write_lock;
73 
74 	// get the write lock
75 	TRACE(("debugger_write(): acquiring write lock...\n"));
76 	error = acquire_sem_etc(writeLock, 1,
77 		(dontWait ? B_RELATIVE_TIMEOUT : B_KILL_CAN_INTERRUPT), 0);
78 	if (error != B_OK) {
79 		TRACE(("debugger_write() done1: %lx\n", error));
80 		return error;
81 	}
82 
83 	// re-get the team debug info
84 	get_team_debug_info(teamDebugInfo);
85 
86 	if (teamDebugInfo.debugger_port != port
87 		|| (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_HANDOVER)) {
88 		// The debugger has changed in the meantime or we are about to be
89 		// handed over to a new debugger. In either case we don't send the
90 		// message.
91 		TRACE(("debugger_write(): %s\n",
92 			(teamDebugInfo.debugger_port != port ? "debugger port changed"
93 				: "handover flag set")));
94 	} else {
95 		TRACE(("debugger_write(): writing to port...\n"));
96 
97 		error = write_port_etc(port, code, buffer, bufferSize,
98 			(dontWait ? B_RELATIVE_TIMEOUT : B_KILL_CAN_INTERRUPT), 0);
99 	}
100 
101 	// release the write lock
102 	release_sem(writeLock);
103 
104 	TRACE(("debugger_write() done: %lx\n", error));
105 
106 	return error;
107 }
108 
109 
110 /**
111  *	For the first initialization the function must be called with \a initLock
112  *	set to \c true. If it would be possible that another thread accesses the
113  *	structure at the same time, `lock' must be held when calling the function.
114  */
115 void
116 clear_team_debug_info(struct team_debug_info *info, bool initLock)
117 {
118 	if (info) {
119 		arch_clear_team_debug_info(&info->arch_info);
120 		atomic_set(&info->flags, B_TEAM_DEBUG_DEFAULT_FLAGS);
121 		info->debugger_team = -1;
122 		info->debugger_port = -1;
123 		info->nub_thread = -1;
124 		info->nub_port = -1;
125 		info->debugger_write_lock = -1;
126 
127 		if (initLock)
128 			info->lock = 0;
129 	}
130 }
131 
132 /**
133  *  `lock' must not be held nor may interrupts be disabled.
134  *  \a info must not be a member of a team struct (or the team struct must no
135  *  longer be accessible, i.e. the team should already be removed).
136  *
137  *	In case the team is still accessible, the procedure is:
138  *	1. get `lock'
139  *	2. copy the team debug info on stack
140  *	3. call clear_team_debug_info() on the team debug info
141  *	4. release `lock'
142  *	5. call destroy_team_debug_info() on the copied team debug info
143  */
144 void
145 destroy_team_debug_info(struct team_debug_info *info)
146 {
147 	if (info) {
148 		arch_destroy_team_debug_info(&info->arch_info);
149 
150 		// delete the debugger port write lock
151 		if (info->debugger_write_lock >= 0) {
152 			delete_sem(info->debugger_write_lock);
153 			info->debugger_write_lock = -1;
154 		}
155 
156 		// delete the nub port
157 		if (info->nub_port >= 0) {
158 			set_port_owner(info->nub_port, B_CURRENT_TEAM);
159 			delete_port(info->nub_port);
160 			info->nub_port = -1;
161 		}
162 
163 		// wait for the nub thread
164 		if (info->nub_thread >= 0) {
165 			if (info->nub_thread != thread_get_current_thread()->id) {
166 				int32 result;
167 				wait_for_thread(info->nub_thread, &result);
168 			}
169 
170 			info->nub_thread = -1;
171 		}
172 
173 		atomic_set(&info->flags, 0);
174 		info->debugger_team = -1;
175 		info->debugger_port = -1;
176 	}
177 }
178 
179 
180 void
181 clear_thread_debug_info(struct thread_debug_info *info, bool dying)
182 {
183 	if (info) {
184 		arch_clear_thread_debug_info(&info->arch_info);
185 		atomic_set(&info->flags,
186 			B_THREAD_DEBUG_DEFAULT_FLAGS | (dying ? B_THREAD_DEBUG_DYING : 0));
187 		info->debug_port = -1;
188 		info->ignore_signals = 0;
189 		info->ignore_signals_once = 0;
190 	}
191 }
192 
193 
194 void
195 destroy_thread_debug_info(struct thread_debug_info *info)
196 {
197 	if (info) {
198 		arch_destroy_thread_debug_info(&info->arch_info);
199 
200 		if (info->debug_port >= 0) {
201 			delete_port(info->debug_port);
202 			info->debug_port = -1;
203 		}
204 
205 		info->ignore_signals = 0;
206 		info->ignore_signals_once = 0;
207 
208 		atomic_set(&info->flags, 0);
209 	}
210 }
211 
212 
213 void
214 user_debug_prepare_for_exec()
215 {
216 	struct thread *thread = thread_get_current_thread();
217 	struct team *team = thread->team;
218 
219 	// If a debugger is installed for the team and the thread debug stuff
220 	// initialized, changed the ownership of the debug port for the thread
221 	// to the kernel team, since exec_team() deletes all ports owned by this
222 	// team. We change the ownership back later.
223 	if (atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
224 		// get the port
225 		port_id debugPort = -1;
226 
227 		cpu_status state = disable_interrupts();
228 		GRAB_THREAD_LOCK();
229 
230 		if (thread->debug_info.flags & B_THREAD_DEBUG_INITIALIZED)
231 			debugPort = thread->debug_info.debug_port;
232 
233 		RELEASE_THREAD_LOCK();
234 		restore_interrupts(state);
235 
236 		// set the new port ownership
237 		if (debugPort >= 0)
238 			set_port_owner(debugPort, team_get_kernel_team_id());
239 	}
240 }
241 
242 
243 void
244 user_debug_finish_after_exec()
245 {
246 	struct thread *thread = thread_get_current_thread();
247 	struct team *team = thread->team;
248 
249 	// If a debugger is installed for the team and the thread debug stuff
250 	// initialized for this thread, change the ownership of its debug port
251 	// back to this team.
252 	if (atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
253 		// get the port
254 		port_id debugPort = -1;
255 
256 		cpu_status state = disable_interrupts();
257 		GRAB_THREAD_LOCK();
258 
259 		if (thread->debug_info.flags & B_THREAD_DEBUG_INITIALIZED)
260 			debugPort = thread->debug_info.debug_port;
261 
262 		RELEASE_THREAD_LOCK();
263 		restore_interrupts(state);
264 
265 		// set the new port ownership
266 		if (debugPort >= 0)
267 			set_port_owner(debugPort, team->id);
268 	}
269 }
270 
271 
272 void
273 init_user_debug()
274 {
275 	#ifdef ARCH_INIT_USER_DEBUG
276 		ARCH_INIT_USER_DEBUG();
277 	#endif
278 }
279 
280 
281 static void
282 get_team_debug_info(team_debug_info &teamDebugInfo)
283 {
284 	struct thread *thread = thread_get_current_thread();
285 
286 	cpu_status state = disable_interrupts();
287 	GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
288 
289 	memcpy(&teamDebugInfo, &thread->team->debug_info, sizeof(team_debug_info));
290 
291 	RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
292 	restore_interrupts(state);
293 }
294 
295 
296 static status_t
297 thread_hit_debug_event_internal(debug_debugger_message event,
298 	const void *message, int32 size, bool requireDebugger, bool &restart)
299 {
300 	restart = false;
301 	struct thread *thread = thread_get_current_thread();
302 
303 	TRACE(("thread_hit_debug_event(): thread: %ld, event: %lu, message: %p, "
304 		"size: %ld\n", thread->id, (uint32)event, message, size));
305 
306 	// check, if there's a debug port already
307 	bool setPort = !(atomic_get(&thread->debug_info.flags)
308 		& B_THREAD_DEBUG_INITIALIZED);
309 
310 	// create a port, if there is none yet
311 	port_id port = -1;
312 	if (setPort) {
313 		char nameBuffer[128];
314 		snprintf(nameBuffer, sizeof(nameBuffer), "nub to thread %ld",
315 			thread->id);
316 
317 		port = create_port(1, nameBuffer);
318 		if (port < 0) {
319 			dprintf("thread_hit_debug_event(): Failed to create debug port: "
320 				"%s\n", strerror(port));
321 			return port;
322 		}
323 
324 		setPort = true;
325 	}
326 
327 	// check the debug info structures once more: get the debugger port, set
328 	// the thread's debug port, and update the thread's debug flags
329 	port_id deletePort = port;
330 	port_id debuggerPort = -1;
331 	port_id nubPort = -1;
332 	status_t error = B_OK;
333 	cpu_status state = disable_interrupts();
334 	GRAB_THREAD_LOCK();
335 	GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
336 
337 	uint32 threadFlags = thread->debug_info.flags;
338 	threadFlags &= ~B_THREAD_DEBUG_STOP;
339 	bool debuggerInstalled
340 		= (thread->team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED);
341 	if (debuggerInstalled || !requireDebugger) {
342 		if (debuggerInstalled) {
343 			debuggerPort = thread->team->debug_info.debugger_port;
344 			nubPort = thread->team->debug_info.nub_port;
345 		}
346 
347 		if (setPort) {
348 			if (threadFlags & B_THREAD_DEBUG_INITIALIZED) {
349 				// someone created a port for us (the port we've created will
350 				// be deleted below)
351 				port = thread->debug_info.debug_port;
352 			} else {
353 				thread->debug_info.debug_port = port;
354 				deletePort = -1;	// keep the port
355 				threadFlags |= B_THREAD_DEBUG_INITIALIZED;
356 			}
357 		} else {
358 			if (threadFlags & B_THREAD_DEBUG_INITIALIZED) {
359 				port = thread->debug_info.debug_port;
360 			} else {
361 				// someone deleted our port
362 				error = B_ERROR;
363 			}
364 		}
365 	} else
366 		error = B_ERROR;
367 
368 	// update the flags
369 	if (error == B_OK)
370 		threadFlags |= B_THREAD_DEBUG_STOPPED;
371 	atomic_set(&thread->debug_info.flags, threadFlags);
372 
373 	RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
374 	RELEASE_THREAD_LOCK();
375 	restore_interrupts(state);
376 
377 	// delete the superfluous port
378 	if (deletePort >= 0)
379 		delete_port(deletePort);
380 
381 	if (error != B_OK) {
382 		TRACE(("thread_hit_debug_event() error: thread: %ld, error: %lx\n",
383 			thread->id, error));
384 		return error;
385 	}
386 
387 	// send a message to the debugger port
388 	if (debuggerInstalled) {
389 		// update the message's origin info first
390 		debug_origin *origin = (debug_origin *)message;
391 		origin->thread = thread->id;
392 		origin->team = thread->team->id;
393 		origin->nub_port = nubPort;
394 
395 		TRACE(("thread_hit_debug_event(): thread: %ld, sending message to "
396 			"debugger port %ld\n", thread->id, debuggerPort));
397 
398 		error = debugger_write(debuggerPort, event, message, size, false);
399 	}
400 
401 	status_t result = B_THREAD_DEBUG_HANDLE_EVENT;
402 	bool singleStep = false;
403 
404 	if (error == B_OK) {
405 		bool done = false;
406 		while (!done) {
407 			// read a command from the debug port
408 			int32 command;
409 			debugged_thread_message_data commandMessage;
410 			ssize_t commandMessageSize = kill_interruptable_read_port(port,
411 				&command, &commandMessage, sizeof(commandMessage));
412 			if (commandMessageSize < 0) {
413 				error = commandMessageSize;
414 				TRACE(("thread_hit_debug_event(): thread: %ld, failed "
415 					"to receive message from port %ld: %lx\n",
416 					thread->id, port, error));
417 				break;
418 			}
419 
420 			switch (command) {
421 				case B_DEBUGGED_THREAD_MESSAGE_CONTINUE:
422 					TRACE(("thread_hit_debug_event(): thread: %ld: "
423 						"B_DEBUGGED_THREAD_MESSAGE_CONTINUE\n",
424 						thread->id));
425 					result = commandMessage.continue_thread.handle_event;
426 
427 					singleStep = commandMessage.continue_thread.single_step;
428 					done = true;
429 					break;
430 
431 				case B_DEBUGGED_THREAD_SET_CPU_STATE:
432 				{
433 					TRACE(("thread_hit_debug_event(): thread: %ld: "
434 						"B_DEBUGGED_THREAD_SET_CPU_STATE\n",
435 						thread->id));
436 					arch_set_debug_cpu_state(
437 						&commandMessage.set_cpu_state.cpu_state);
438 
439 					break;
440 				}
441 
442 				case B_DEBUGGED_THREAD_GET_CPU_STATE:
443 				{
444 					port_id replyPort = commandMessage.get_cpu_state.reply_port;
445 
446 					// prepare the message
447 					debug_nub_get_cpu_state_reply replyMessage;
448 					replyMessage.error = B_OK;
449 					replyMessage.message = event;
450 					arch_get_debug_cpu_state(&replyMessage.cpu_state);
451 
452 					// send it
453 					error = kill_interruptable_write_port(replyPort, event,
454 						&replyMessage, sizeof(replyMessage));
455 
456 					break;
457 				}
458 
459 				case B_DEBUGGED_THREAD_DEBUGGER_CHANGED:
460 				{
461 					// Check, if the debugger really changed, i.e. is different
462 					// than the one we know.
463 					team_debug_info teamDebugInfo;
464 					get_team_debug_info(teamDebugInfo);
465 
466 					if (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
467 						if (!debuggerInstalled
468 							|| teamDebugInfo.debugger_port != debuggerPort) {
469 							// debugger was installed or has changed: restart
470 							// this function
471 							restart = true;
472 							done = true;
473 						}
474 					} else {
475 						if (debuggerInstalled) {
476 							// debugger is gone: continue the thread normally
477 							done = true;
478 						}
479 					}
480 
481 					break;
482 				}
483 			}
484 		}
485 	} else {
486 		TRACE(("thread_hit_debug_event(): thread: %ld, failed to send "
487 			"message to debugger port %ld: %lx\n", thread->id,
488 			debuggerPort, error));
489 	}
490 
491 	// update the thread debug info
492 	bool destroyThreadInfo = false;
493 	thread_debug_info threadDebugInfo;
494 
495 	state = disable_interrupts();
496 	GRAB_THREAD_LOCK();
497 
498 	// check, if the team is still being debugged
499 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
500 	if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
501 		// update the single-step flag
502 		if (singleStep) {
503 			atomic_or(&thread->debug_info.flags,
504 				B_THREAD_DEBUG_SINGLE_STEP);
505 		} else {
506 			atomic_and(&thread->debug_info.flags,
507 				~B_THREAD_DEBUG_SINGLE_STEP);
508 		}
509 
510 		// unset the "stopped" state
511 		atomic_and(&thread->debug_info.flags, ~B_THREAD_DEBUG_STOPPED);
512 
513 	} else {
514 		// the debugger is gone: cleanup our info completely
515 		threadDebugInfo = thread->debug_info;
516 		clear_thread_debug_info(&thread->debug_info, false);
517 		destroyThreadInfo = true;
518 	}
519 
520 	RELEASE_THREAD_LOCK();
521 	restore_interrupts(state);
522 
523 	if (destroyThreadInfo)
524 		destroy_thread_debug_info(&threadDebugInfo);
525 
526 	return (error == B_OK ? result : error);
527 }
528 
529 
530 static status_t
531 thread_hit_debug_event(debug_debugger_message event, const void *message,
532 	int32 size, bool requireDebugger)
533 {
534 	status_t result;
535 	bool restart;
536 	do {
537 		restart = false;
538 		result = thread_hit_debug_event_internal(event, message, size,
539 			requireDebugger, restart);
540 	} while (result >= 0 && restart);
541 
542 	return result;
543 }
544 
545 
546 void
547 user_debug_pre_syscall(uint32 syscall, void *args)
548 {
549 	// check whether a debugger is installed
550 	struct thread *thread = thread_get_current_thread();
551 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
552 	if (!(teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED))
553 		return;
554 
555 	// check whether pre-syscall tracing is enabled for team or thread
556 	int32 threadDebugFlags = atomic_get(&thread->debug_info.flags);
557 	if (!(teamDebugFlags & B_TEAM_DEBUG_PRE_SYSCALL)
558 			&& !(threadDebugFlags & B_THREAD_DEBUG_PRE_SYSCALL)) {
559 		return;
560 	}
561 
562 	// prepare the message
563 	debug_pre_syscall message;
564 	message.syscall = syscall;
565 
566 	// copy the syscall args
567 	if (syscall < (uint32)kSyscallCount) {
568 		if (kSyscallInfos[syscall].parameter_size > 0)
569 			memcpy(message.args, args, kSyscallInfos[syscall].parameter_size);
570 	}
571 
572 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_PRE_SYSCALL, &message,
573 		sizeof(message), true);
574 }
575 
576 
577 void
578 user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
579 	bigtime_t startTime)
580 {
581 	// check whether a debugger is installed
582 	struct thread *thread = thread_get_current_thread();
583 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
584 	if (!(teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED))
585 		return;
586 
587 	// check whether post-syscall tracing is enabled for team or thread
588 	int32 threadDebugFlags = atomic_get(&thread->debug_info.flags);
589 	if (!(teamDebugFlags & B_TEAM_DEBUG_POST_SYSCALL)
590 			&& !(threadDebugFlags & B_THREAD_DEBUG_POST_SYSCALL)) {
591 		return;
592 	}
593 
594 	// prepare the message
595 	debug_post_syscall message;
596 	message.start_time = startTime;
597 	message.end_time = system_time();
598 	message.return_value = returnValue;
599 	message.syscall = syscall;
600 
601 	// copy the syscall args
602 	if (syscall < (uint32)kSyscallCount) {
603 		if (kSyscallInfos[syscall].parameter_size > 0)
604 			memcpy(message.args, args, kSyscallInfos[syscall].parameter_size);
605 	}
606 
607 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_POST_SYSCALL, &message,
608 		sizeof(message), true);
609 }
610 
611 
612 /**	\brief To be called when an unhandled processor fault (exception/error)
613  *		   occurred.
614  *	\param fault The debug_why_stopped value identifying the kind of fault.
615  *	\return \c true, if the caller shall continue normally, i.e. usually send
616  *			a deadly signal. \c false, if the debugger insists to continue the
617  *			program (e.g. because it has solved the removed the cause of the
618  *			problem).
619  */
620 bool
621 user_debug_exception_occurred(debug_exception_type exception, int signal)
622 {
623 	// ensure that a debugger is installed for this team
624 	struct thread *thread = thread_get_current_thread();
625 	port_id nubPort;
626 	status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
627 	if (error != B_OK) {
628 		dprintf("user_debug_exception_occurred(): Failed to install debugger: "
629 			"thread: %ld: %s\n", thread->id, strerror(error));
630 		return error;
631 	}
632 
633 	// prepare the message
634 	debug_exception_occurred message;
635 	message.exception = exception;
636 	message.signal = signal;
637 
638 	status_t result = thread_hit_debug_event(
639 		B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED, &message, sizeof(message), true);
640 	return (result != B_THREAD_DEBUG_IGNORE_EVENT);
641 }
642 
643 
644 bool
645 user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly)
646 {
647 	// check, if a debugger is installed and is interested in signals
648 	struct thread *thread = thread_get_current_thread();
649 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
650 	if (~teamDebugFlags
651 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_SIGNALS)) {
652 		return true;
653 	}
654 
655 	// prepare the message
656 	debug_signal_received message;
657 	message.signal = signal;
658 	message.handler = *handler;
659 	message.deadly = deadly;
660 
661 	status_t result = thread_hit_debug_event(B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,
662 		&message, sizeof(message), true);
663 	return (result != B_THREAD_DEBUG_IGNORE_EVENT);
664 }
665 
666 
667 void
668 user_debug_stop_thread()
669 {
670 	// ensure that a debugger is installed for this team
671 	struct thread *thread = thread_get_current_thread();
672 	port_id nubPort;
673 	status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
674 	if (error != B_OK) {
675 		dprintf("user_debug_stop_thread(): Failed to install debugger: "
676 			"thread: %ld: %s\n", thread->id, strerror(error));
677 		return;
678 	}
679 
680 	// prepare the message
681 	debug_thread_debugged message;
682 
683 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, &message,
684 		sizeof(message), true);
685 }
686 
687 
688 void
689 user_debug_team_created(team_id teamID)
690 {
691 	// check, if a debugger is installed and is interested in team creation
692 	// events
693 	struct thread *thread = thread_get_current_thread();
694 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
695 	if (~teamDebugFlags
696 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_TEAM_CREATION)) {
697 		return;
698 	}
699 
700 	// prepare the message
701 	debug_team_created message;
702 	message.new_team = teamID;
703 
704 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_TEAM_CREATED, &message,
705 		sizeof(message), true);
706 }
707 
708 
709 void
710 user_debug_team_deleted(team_id teamID, port_id debuggerPort)
711 {
712 	if (debuggerPort >= 0) {
713 		TRACE(("user_debug_team_deleted(team: %ld, debugger port: %ld)\n",
714 			teamID, debuggerPort));
715 
716 		debug_team_deleted message;
717 		message.origin.thread = -1;
718 		message.origin.team = teamID;
719 		message.origin.nub_port = -1;
720 		write_port_etc(debuggerPort, B_DEBUGGER_MESSAGE_TEAM_DELETED, &message,
721 			sizeof(message), B_RELATIVE_TIMEOUT, 0);
722 			// TODO: Would it be OK to wait here?
723 	}
724 }
725 
726 
727 void
728 user_debug_thread_created(thread_id threadID)
729 {
730 	// check, if a debugger is installed and is interested in thread events
731 	struct thread *thread = thread_get_current_thread();
732 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
733 	if (~teamDebugFlags
734 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_THREADS)) {
735 		return;
736 	}
737 
738 	// prepare the message
739 	debug_thread_created message;
740 	message.new_thread = threadID;
741 
742 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_CREATED, &message,
743 		sizeof(message), true);
744 }
745 
746 
747 void
748 user_debug_thread_deleted(team_id teamID, thread_id threadID)
749 {
750 	// get the team debug flags and debugger port
751 	cpu_status state = disable_interrupts();
752 	GRAB_TEAM_LOCK();
753 
754 	struct team *team = team_get_team_struct_locked(teamID);
755 
756 	int32 teamDebugFlags = 0;
757 	port_id debuggerPort = -1;
758 	if (team) {
759 		GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
760 
761 		teamDebugFlags = atomic_get(&team->debug_info.flags);
762 		debuggerPort = team->debug_info.debugger_port;
763 
764 		RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
765 	}
766 
767 	RELEASE_TEAM_LOCK();
768 	restore_interrupts(state);
769 
770 	// check, if a debugger is installed and is interested in thread events
771 	if (~teamDebugFlags
772 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_THREADS)) {
773 		return;
774 	}
775 
776 	// notify the debugger
777 	if (debuggerPort >= 0) {
778 		debug_thread_deleted message;
779 		message.origin.thread = threadID;
780 		message.origin.team = teamID;
781 		message.origin.nub_port = -1;
782 		debugger_write(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED,
783 			&message, sizeof(message), true);
784 			// TODO: Would it be OK to wait here?
785 	}
786 }
787 
788 
789 void
790 user_debug_image_created(const image_info *imageInfo)
791 {
792 	// check, if a debugger is installed and is interested in image events
793 	struct thread *thread = thread_get_current_thread();
794 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
795 	if (~teamDebugFlags
796 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_IMAGES)) {
797 		return;
798 	}
799 
800 	// prepare the message
801 	debug_image_created message;
802 	memcpy(&message.info, imageInfo, sizeof(image_info));
803 
804 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
805 		sizeof(message), true);
806 }
807 
808 
809 void
810 user_debug_image_deleted(const image_info *imageInfo)
811 {
812 	// check, if a debugger is installed and is interested in image events
813 	struct thread *thread = thread_get_current_thread();
814 	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);
815 	if (~teamDebugFlags
816 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_IMAGES)) {
817 		return;
818 	}
819 
820 	// prepare the message
821 	debug_image_deleted message;
822 	memcpy(&message.info, imageInfo, sizeof(image_info));
823 
824 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message,
825 		sizeof(message), true);
826 }
827 
828 
829 void
830 user_debug_breakpoint_hit(bool software)
831 {
832 	// ensure that a debugger is installed for this team
833 	struct thread *thread = thread_get_current_thread();
834 	port_id nubPort;
835 	status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
836 	if (error != B_OK) {
837 		dprintf("user_debug_breakpoint_hit(): Failed to install debugger: "
838 			"thread: %ld: %s\n", thread->id, strerror(error));
839 		return;
840 	}
841 
842 	// prepare the message
843 	debug_breakpoint_hit message;
844 	message.software = software;
845 	arch_get_debug_cpu_state(&message.cpu_state);
846 
847 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_BREAKPOINT_HIT, &message,
848 		sizeof(message), true);
849 }
850 
851 
852 void
853 user_debug_watchpoint_hit()
854 {
855 	// ensure that a debugger is installed for this team
856 	struct thread *thread = thread_get_current_thread();
857 	port_id nubPort;
858 	status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
859 	if (error != B_OK) {
860 		dprintf("user_debug_watchpoint_hit(): Failed to install debugger: "
861 			"thread: %ld: %s\n", thread->id, strerror(error));
862 		return;
863 	}
864 
865 	// prepare the message
866 	debug_watchpoint_hit message;
867 	arch_get_debug_cpu_state(&message.cpu_state);
868 
869 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_WATCHPOINT_HIT, &message,
870 		sizeof(message), true);
871 }
872 
873 
874 void
875 user_debug_single_stepped()
876 {
877 	// ensure that a debugger is installed for this team
878 	struct thread *thread = thread_get_current_thread();
879 	port_id nubPort;
880 	status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
881 	if (error != B_OK) {
882 		dprintf("user_debug_watchpoint_hit(): Failed to install debugger: "
883 			"thread: %ld: %s\n", thread->id, strerror(error));
884 		return;
885 	}
886 
887 	// prepare the message
888 	debug_single_step message;
889 	arch_get_debug_cpu_state(&message.cpu_state);
890 
891 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_SINGLE_STEP, &message,
892 		sizeof(message), true);
893 }
894 
895 
896 /**	\brief Called by the debug nub thread of a team to broadcast a message
897  *		   that are initialized for debugging (and thus have a debug port).
898  */
899 static void
900 broadcast_debugged_thread_message(struct thread *nubThread, int32 code,
901 	const void *message, int32 size)
902 {
903 	// iterate through the threads
904 	thread_info threadInfo;
905 	int32 cookie = 0;
906 	while (get_next_thread_info(nubThread->team->id, &cookie, &threadInfo)
907 			== B_OK) {
908 		// find the thread and get its debug port
909 		cpu_status state = disable_interrupts();
910 		GRAB_THREAD_LOCK();
911 
912 		port_id threadDebugPort = -1;
913 		thread_id threadID = -1;
914 		struct thread *thread
915 			= thread_get_thread_struct_locked(threadInfo.thread);
916 		if (thread && thread != nubThread && thread->team == nubThread->team
917 			&& thread->debug_info.flags & B_THREAD_DEBUG_INITIALIZED) {
918 			threadDebugPort = thread->debug_info.debug_port;
919 			threadID = thread->id;
920 		}
921 
922 		RELEASE_THREAD_LOCK();
923 		restore_interrupts(state);
924 
925 		// send the message to the thread
926 		if (threadDebugPort >= 0) {
927 			status_t error = kill_interruptable_write_port(threadDebugPort,
928 				code, message, size);
929 			if (error != B_OK) {
930 				TRACE(("broadcast_debugged_thread_message(): Failed to send "
931 					"message to thread %ld: %lx\n", threadID, error));
932 			}
933 		}
934 	}
935 }
936 
937 
938 static void
939 nub_thread_cleanup(struct thread *nubThread)
940 {
941 	TRACE(("nub_thread_cleanup(%ld): debugger port: %ld\n", nubThread->id,
942 		nubThread->team->debug_info.debugger_port));
943 
944 	team_debug_info teamDebugInfo;
945 	bool destroyDebugInfo = false;
946 
947 	cpu_status state = disable_interrupts();
948 	GRAB_TEAM_LOCK();
949 	GRAB_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info);
950 
951 	team_debug_info &info = nubThread->team->debug_info;
952 	if (info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED
953 		&& info.nub_thread == nubThread->id) {
954 		teamDebugInfo = info;
955 		clear_team_debug_info(&info, false);
956 		destroyDebugInfo = true;
957 	}
958 
959 	RELEASE_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info);
960 	RELEASE_TEAM_LOCK();
961 	restore_interrupts(state);
962 
963 	if (destroyDebugInfo)
964 		destroy_team_debug_info(&teamDebugInfo);
965 
966 	// notify all threads that the debugger is gone
967 	broadcast_debugged_thread_message(nubThread,
968 		B_DEBUGGED_THREAD_DEBUGGER_CHANGED, NULL, 0);
969 }
970 
971 
972 /**	\brief Reads data from user memory.
973  *
974  *	Tries to read \a size bytes of data from user memory address \a address
975  *	into the supplied buffer \a buffer. If only a part could be read the
976  *	function won't fail. The number of bytes actually read is return through
977  *	\a bytesRead.
978  *
979  *	\param address The user memory address from which to read.
980  *	\param buffer The buffer into which to write.
981  *	\param size The number of bytes to read.
982  *	\param bytesRead Will be set to the number of bytes actually read.
983  *	\return \c B_OK, if reading went fine. Then \a bytesRead will be set to
984  *			the amount of data actually read. An error indicates that nothing
985  *			has been read.
986  */
987 static status_t
988 read_user_memory(const void *_address, void *_buffer, int32 size,
989 	int32 &bytesRead)
990 {
991 	const char *address = (const char*)_address;
992 	char *buffer = (char*)_buffer;
993 
994 	// check the parameters
995 	if (!IS_USER_ADDRESS(address))
996 		return B_BAD_ADDRESS;
997 	if (size <= 0)
998 		return B_BAD_VALUE;
999 
1000 	// If the region to be read crosses page boundaries, we split it up into
1001 	// smaller chunks.
1002 	status_t error = B_OK;
1003 	bytesRead = 0;
1004 	while (size > 0) {
1005 		// check whether we're still in user address space
1006 		if (!IS_USER_ADDRESS(address)) {
1007 			error = B_BAD_ADDRESS;
1008 			break;
1009 		}
1010 
1011 		// don't cross page boundaries in a single read
1012 		int32 toRead = size;
1013 		int32 maxRead = B_PAGE_SIZE - (addr_t)address % B_PAGE_SIZE;
1014 		if (toRead > maxRead)
1015 			toRead = maxRead;
1016 
1017 		error = user_memcpy(buffer, address, toRead);
1018 		if (error != B_OK)
1019 			break;
1020 
1021 		bytesRead += toRead;
1022 		address += toRead;
1023 		buffer += toRead;
1024 		size -= toRead;
1025 	}
1026 
1027 	// If reading fails, we only fail, if we haven't read anything yet.
1028 	if (error != B_OK) {
1029 		if (bytesRead > 0)
1030 			return B_OK;
1031 		return error;
1032 	}
1033 
1034 	return B_OK;
1035 }
1036 
1037 
1038 static status_t
1039 write_user_memory(void *_address, const void *_buffer, int32 size,
1040 	int32 &bytesWritten)
1041 {
1042 	char *address = (char*)_address;
1043 	const char *buffer = (const char*)_buffer;
1044 
1045 	// check the parameters
1046 	if (!IS_USER_ADDRESS(address))
1047 		return B_BAD_ADDRESS;
1048 	if (size <= 0)
1049 		return B_BAD_VALUE;
1050 
1051 	// If the region to be written crosses area boundaries, we split it up into
1052 	// smaller chunks.
1053 	status_t error = B_OK;
1054 	bytesWritten = 0;
1055 	while (size > 0) {
1056 		// check whether we're still in user address space
1057 		if (!IS_USER_ADDRESS(address)) {
1058 			error = B_BAD_ADDRESS;
1059 			break;
1060 		}
1061 
1062 		// get the area for the address (we need to use _user_area_for(), since
1063 		// we're looking for a user area)
1064 		area_id area = _user_area_for((void*)address);
1065 		if (area < 0) {
1066 			TRACE(("write_user_memory(): area not found for address: %p: "
1067 				"%lx\n", address, area));
1068 			error = area;
1069 			break;
1070 		}
1071 
1072 		area_info areaInfo;
1073 		status_t error = get_area_info(area, &areaInfo);
1074 		if (error != B_OK) {
1075 			TRACE(("write_user_memory(): failed to get info for area %ld: "
1076 				"%lx\n", area, error));
1077 			error = B_BAD_ADDRESS;
1078 			break;
1079 		}
1080 
1081 		// restrict this round of writing to the found area
1082 		int32 toWrite = size;
1083 		int32 maxWrite = (char*)areaInfo.address + areaInfo.size - address;
1084 		if (toWrite > maxWrite)
1085 			toWrite = maxWrite;
1086 
1087 		// if the area is read-only, we temporarily need to make it writable
1088 		bool protectionChanged = false;
1089 		if (!(areaInfo.protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA))) {
1090 			error = set_area_protection(area,
1091 				areaInfo.protection | B_WRITE_AREA);
1092 			if (error != B_OK) {
1093 				TRACE(("write_user_memory(): failed to set new protection for "
1094 					"area %ld: %lx\n", area, error));
1095 				break;
1096 			}
1097 			protectionChanged = true;
1098 		}
1099 
1100 		// copy the memory
1101 		error = user_memcpy(address, buffer, toWrite);
1102 
1103 		// reset the area protection
1104 		if (protectionChanged)
1105 			set_area_protection(area, areaInfo.protection);
1106 
1107 		if (error != B_OK) {
1108 			TRACE(("write_user_memory(): user_memcpy() failed: %lx\n", error));
1109 			break;
1110 		}
1111 
1112 		bytesWritten += toWrite;
1113 		address += toWrite;
1114 		buffer += toWrite;
1115 		size -= toWrite;
1116 	}
1117 
1118 	// If writing fails, we only fail, if we haven't written anything yet.
1119 	if (error != B_OK) {
1120 		if (bytesWritten > 0)
1121 			return B_OK;
1122 		return error;
1123 	}
1124 
1125 	return B_OK;
1126 }
1127 
1128 
1129 /**	\brief Debug nub thread helper function that returns the debug port of
1130  *		   a thread of the same team.
1131  */
1132 static status_t
1133 debug_nub_thread_get_thread_debug_port(struct thread *nubThread,
1134 	thread_id threadID, port_id &threadDebugPort)
1135 {
1136 	status_t result = B_OK;
1137 	threadDebugPort = -1;
1138 
1139 	cpu_status state = disable_interrupts();
1140 	GRAB_THREAD_LOCK();
1141 
1142 	struct thread *thread = thread_get_thread_struct_locked(threadID);
1143 	if (thread) {
1144 		if (thread->team != nubThread->team)
1145 			result = B_BAD_VALUE;
1146 		else if (thread->debug_info.flags & B_THREAD_DEBUG_STOPPED)
1147 			threadDebugPort = thread->debug_info.debug_port;
1148 		else
1149 			result = B_BAD_VALUE;
1150 	} else
1151 		result = B_BAD_THREAD_ID;
1152 
1153 	RELEASE_THREAD_LOCK();
1154 	restore_interrupts(state);
1155 
1156 	if (result == B_OK && threadDebugPort < 0)
1157 		result = B_ERROR;
1158 
1159 	return result;
1160 }
1161 
1162 
1163 static status_t
1164 debug_nub_thread(void *)
1165 {
1166 	struct thread *nubThread = thread_get_current_thread();
1167 
1168 	// check, if we're still the current nub thread and get our port
1169 	cpu_status state = disable_interrupts();
1170 
1171 	GRAB_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info);
1172 
1173 	if (nubThread->team->debug_info.nub_thread != nubThread->id)
1174 		return 0;
1175 
1176 	port_id port = nubThread->team->debug_info.nub_port;
1177 	sem_id writeLock = nubThread->team->debug_info.debugger_write_lock;
1178 
1179 	RELEASE_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info);
1180 	restore_interrupts(state);
1181 
1182 	TRACE(("debug_nub_thread() thread: %ld, team %ld, nub port: %ld\n",
1183 		nubThread->id, nubThread->team->id, port));
1184 
1185 	// notify all threads that a debugger has been installed
1186 	broadcast_debugged_thread_message(nubThread,
1187 		B_DEBUGGED_THREAD_DEBUGGER_CHANGED, NULL, 0);
1188 
1189 	// command processing loop
1190 	while (true) {
1191 		int32 command;
1192 		debug_nub_message_data message;
1193 		ssize_t messageSize = kill_interruptable_read_port(port, &command,
1194 			&message, sizeof(message));
1195 
1196 		if (messageSize < 0) {
1197 			// The port is not longer valid or we were interrupted by a kill
1198 			// signal: If we are still listed in the team's debug info as nub
1199 			// thread, we need to update that.
1200 			nub_thread_cleanup(nubThread);
1201 
1202 			TRACE(("nub thread %ld: terminating: %lx\n", nubThread->id,
1203 				messageSize));
1204 
1205 			return messageSize;
1206 		}
1207 
1208 		bool sendReply = false;
1209 		union {
1210 			debug_nub_read_memory_reply			read_memory;
1211 			debug_nub_write_memory_reply		write_memory;
1212 			debug_nub_get_cpu_state_reply		get_cpu_state;
1213 			debug_nub_set_breakpoint_reply		set_breakpoint;
1214 			debug_nub_set_watchpoint_reply		set_watchpoint;
1215 			debug_nub_get_signal_masks_reply	get_signal_masks;
1216 			debug_nub_get_signal_handler_reply	get_signal_handler;
1217 		} reply;
1218 		int32 replySize = 0;
1219 		port_id replyPort = -1;
1220 
1221 		// process the command
1222 		switch (command) {
1223 			case B_DEBUG_MESSAGE_READ_MEMORY:
1224 			{
1225 				// get the parameters
1226 				replyPort = message.read_memory.reply_port;
1227 				void *address = message.read_memory.address;
1228 				int32 size = message.read_memory.size;
1229 				status_t result = B_OK;
1230 
1231 				// check the parameters
1232 				if (!IS_USER_ADDRESS(address))
1233 					result = B_BAD_ADDRESS;
1234 				else if (size <= 0 || size > B_MAX_READ_WRITE_MEMORY_SIZE)
1235 					result = B_BAD_VALUE;
1236 
1237 				// read the memory
1238 				int32 bytesRead = 0;
1239 				if (result == B_OK) {
1240 					result = read_user_memory(address, reply.read_memory.data,
1241 						size, bytesRead);
1242 				}
1243 				reply.read_memory.error = result;
1244 
1245 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_READ_MEMORY: "
1246 					"reply port: %ld, address: %p, size: %ld, result: %lx, "
1247 					"read: %ld\n", nubThread->id, replyPort, address, size,
1248 					result, bytesRead));
1249 
1250 				// send only as much data as necessary
1251 				reply.read_memory.size = bytesRead;
1252 				replySize = reply.read_memory.data + bytesRead - (char*)&reply;
1253 				sendReply = true;
1254 				break;
1255 			}
1256 
1257 			case B_DEBUG_MESSAGE_WRITE_MEMORY:
1258 			{
1259 				// get the parameters
1260 				replyPort = message.write_memory.reply_port;
1261 				void *address = message.write_memory.address;
1262 				int32 size = message.write_memory.size;
1263 				const char *data = message.write_memory.data;
1264 				int32 realSize = (char*)&message + messageSize - data;
1265 				status_t result = B_OK;
1266 
1267 				// check the parameters
1268 				if (!IS_USER_ADDRESS(address))
1269 					result = B_BAD_ADDRESS;
1270 				else if (size <= 0 || size > realSize)
1271 					result = B_BAD_VALUE;
1272 
1273 				// write the memory
1274 				int32 bytesWritten = 0;
1275 				if (result == B_OK) {
1276 					result = write_user_memory(address, data, size,
1277 						bytesWritten);
1278 				}
1279 				reply.write_memory.error = result;
1280 
1281 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_WRITE_MEMORY: "
1282 					"reply port: %ld, address: %p, size: %ld, result: %lx, "
1283 					"written: %ld\n", nubThread->id, replyPort, address, size,
1284 					result, bytesWritten));
1285 
1286 				reply.write_memory.size = bytesWritten;
1287 				sendReply = true;
1288 				replySize = sizeof(debug_nub_write_memory_reply);
1289 				break;
1290 			}
1291 
1292 			case B_DEBUG_MESSAGE_SET_TEAM_FLAGS:
1293 			{
1294 				// get the parameters
1295 				int32 flags = message.set_team_flags.flags
1296 					& B_TEAM_DEBUG_USER_FLAG_MASK;
1297 
1298 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_TEAM_FLAGS: "
1299 					"flags: %lx\n", nubThread->id, flags));
1300 
1301 				struct team *team = thread_get_current_thread()->team;
1302 
1303 				// set the flags
1304 				cpu_status state = disable_interrupts();
1305 				GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1306 
1307 				flags |= team->debug_info.flags & B_TEAM_DEBUG_KERNEL_FLAG_MASK;
1308 				atomic_set(&team->debug_info.flags, flags);
1309 
1310 				RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1311 				restore_interrupts(state);
1312 
1313 				break;
1314 			}
1315 
1316 			case B_DEBUG_MESSAGE_SET_THREAD_FLAGS:
1317 			{
1318 				// get the parameters
1319 				thread_id threadID = message.set_thread_flags.thread;
1320 				int32 flags = message.set_thread_flags.flags
1321 					& B_THREAD_DEBUG_USER_FLAG_MASK;
1322 
1323 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_THREAD_FLAGS: "
1324 					"thread: %ld, flags: %lx\n", nubThread->id, threadID,
1325 					flags));
1326 
1327 				// set the flags
1328 				cpu_status state = disable_interrupts();
1329 				GRAB_THREAD_LOCK();
1330 
1331 				struct thread *thread
1332 					= thread_get_thread_struct_locked(threadID);
1333 				if (thread
1334 					&& thread->team == thread_get_current_thread()->team) {
1335 					flags |= thread->debug_info.flags
1336 						& B_THREAD_DEBUG_KERNEL_FLAG_MASK;
1337 					atomic_set(&thread->debug_info.flags, flags);
1338 				}
1339 
1340 				RELEASE_THREAD_LOCK();
1341 				restore_interrupts(state);
1342 
1343 				break;
1344 			}
1345 
1346 			case B_DEBUG_MESSAGE_CONTINUE_THREAD:
1347 			{
1348 				// get the parameters
1349 				thread_id threadID;
1350 				uint32 handleEvent;
1351 				bool singleStep;
1352 
1353 				threadID = message.continue_thread.thread;
1354 				handleEvent = message.continue_thread.handle_event;
1355 				singleStep = message.continue_thread.single_step;
1356 
1357 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CONTINUE_THREAD: "
1358 					"thread: %ld, handle event: %lu, single step: %d\n",
1359 					nubThread->id, threadID, handleEvent, singleStep));
1360 
1361 				// find the thread and get its debug port
1362 				port_id threadDebugPort = -1;
1363 				status_t result = debug_nub_thread_get_thread_debug_port(
1364 					nubThread, threadID, threadDebugPort);
1365 
1366 				// send a message to the debugged thread
1367 				if (result == B_OK) {
1368 					debugged_thread_continue commandMessage;
1369 					commandMessage.handle_event = handleEvent;
1370 					commandMessage.single_step = singleStep;
1371 
1372 					result = write_port(threadDebugPort,
1373 						B_DEBUGGED_THREAD_MESSAGE_CONTINUE,
1374 						&commandMessage, sizeof(commandMessage));
1375 				}
1376 
1377 				break;
1378 			}
1379 
1380 			case B_DEBUG_MESSAGE_SET_CPU_STATE:
1381 			{
1382 				// get the parameters
1383 				thread_id threadID = message.set_cpu_state.thread;
1384 				const debug_cpu_state &cpuState
1385 					= message.set_cpu_state.cpu_state;
1386 
1387 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_CPU_STATE: "
1388 					"thread: %ld\n", nubThread->id, threadID));
1389 
1390 				// find the thread and get its debug port
1391 				port_id threadDebugPort = -1;
1392 				status_t result = debug_nub_thread_get_thread_debug_port(
1393 					nubThread, threadID, threadDebugPort);
1394 
1395 				// send a message to the debugged thread
1396 				if (result == B_OK) {
1397 					debugged_thread_set_cpu_state commandMessage;
1398 					memcpy(&commandMessage.cpu_state, &cpuState,
1399 						sizeof(debug_cpu_state));
1400 					write_port(threadDebugPort,
1401 						B_DEBUGGED_THREAD_SET_CPU_STATE,
1402 						&commandMessage, sizeof(commandMessage));
1403 				}
1404 
1405 				break;
1406 			}
1407 
1408 			case B_DEBUG_MESSAGE_GET_CPU_STATE:
1409 			{
1410 				// get the parameters
1411 				thread_id threadID = message.get_cpu_state.thread;
1412 				replyPort = message.get_cpu_state.reply_port;
1413 
1414 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_CPU_STATE: "
1415 					"thread: %ld\n", nubThread->id, threadID));
1416 
1417 				// find the thread and get its debug port
1418 				port_id threadDebugPort = -1;
1419 				status_t result = debug_nub_thread_get_thread_debug_port(
1420 					nubThread, threadID, threadDebugPort);
1421 
1422 				// send a message to the debugged thread
1423 				if (threadDebugPort >= 0) {
1424 					debugged_thread_get_cpu_state commandMessage;
1425 					commandMessage.reply_port = replyPort;
1426 					result = write_port(threadDebugPort,
1427 						B_DEBUGGED_THREAD_GET_CPU_STATE, &commandMessage,
1428 						sizeof(commandMessage));
1429 				}
1430 
1431 				// send a reply to the debugger in case of error
1432 				if (result != B_OK) {
1433 					reply.get_cpu_state.error = result;
1434 					sendReply = true;
1435 					replySize = sizeof(reply.get_cpu_state);
1436 				}
1437 
1438 				break;
1439 			}
1440 
1441 			case B_DEBUG_MESSAGE_SET_BREAKPOINT:
1442 			{
1443 				// get the parameters
1444 				replyPort = message.set_breakpoint.reply_port;
1445 				void *address = message.set_breakpoint.address;
1446 
1447 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_BREAKPOINT: "
1448 					"address: %p\n", nubThread->id, address));
1449 
1450 				// check the address
1451 				status_t result = B_OK;
1452 				if (address == NULL || !IS_USER_ADDRESS(address))
1453 					result = B_BAD_ADDRESS;
1454 
1455 				// set the breakpoint
1456 				if (result == B_OK)
1457 					result = arch_set_breakpoint(address);
1458 
1459 				// prepare the reply
1460 				reply.set_breakpoint.error = result;
1461 				replySize = sizeof(reply.set_breakpoint);
1462 				sendReply = true;
1463 
1464 				break;
1465 			}
1466 
1467 			case B_DEBUG_MESSAGE_CLEAR_BREAKPOINT:
1468 			{
1469 				// get the parameters
1470 				void *address = message.clear_breakpoint.address;
1471 
1472 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CLEAR_BREAKPOINT: "
1473 					"address: %p\n", nubThread->id, address));
1474 
1475 				// check the address
1476 				status_t result = B_OK;
1477 				if (address == NULL || !IS_USER_ADDRESS(address))
1478 					result = B_BAD_ADDRESS;
1479 
1480 				// clear the breakpoint
1481 				if (result == B_OK)
1482 					result = arch_clear_breakpoint(address);
1483 
1484 				break;
1485 			}
1486 
1487 			case B_DEBUG_MESSAGE_SET_WATCHPOINT:
1488 			{
1489 				// get the parameters
1490 				replyPort = message.set_watchpoint.reply_port;
1491 				void *address = message.set_watchpoint.address;
1492 				uint32 type = message.set_watchpoint.type;
1493 				int32 length = message.set_watchpoint.length;
1494 
1495 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_WATCHPOINT: "
1496 					"address: %p, type: %lu, length: %ld\n", nubThread->id,
1497 					address, type, length));
1498 
1499 				// check the address and size
1500 				status_t result = B_OK;
1501 				if (address == NULL || !IS_USER_ADDRESS(address))
1502 					result = B_BAD_ADDRESS;
1503 				if (length < 0)
1504 					result = B_BAD_VALUE;
1505 
1506 				// set the watchpoint
1507 				if (result == B_OK)
1508 					result = arch_set_watchpoint(address, type, length);
1509 
1510 				// prepare the reply
1511 				reply.set_watchpoint.error = result;
1512 				replySize = sizeof(reply.set_watchpoint);
1513 				sendReply = true;
1514 
1515 				break;
1516 			}
1517 
1518 			case B_DEBUG_MESSAGE_CLEAR_WATCHPOINT:
1519 			{
1520 				// get the parameters
1521 				void *address = message.clear_watchpoint.address;
1522 
1523 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CLEAR_WATCHPOINT: "
1524 					"address: %p\n", nubThread->id, address));
1525 
1526 				// check the address
1527 				status_t result = B_OK;
1528 				if (address == NULL || !IS_USER_ADDRESS(address))
1529 					result = B_BAD_ADDRESS;
1530 
1531 				// clear the watchpoint
1532 				if (result == B_OK)
1533 					result = arch_clear_watchpoint(address);
1534 
1535 				break;
1536 			}
1537 
1538 			case B_DEBUG_MESSAGE_SET_SIGNAL_MASKS:
1539 			{
1540 				// get the parameters
1541 				thread_id threadID = message.set_signal_masks.thread;
1542 				uint64 ignore = message.set_signal_masks.ignore_mask;
1543 				uint64 ignoreOnce = message.set_signal_masks.ignore_once_mask;
1544 				uint32 ignoreOp = message.set_signal_masks.ignore_op;
1545 				uint32 ignoreOnceOp = message.set_signal_masks.ignore_once_op;
1546 
1547 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_SIGNAL_MASKS: "
1548 					"thread: %ld, ignore: %llx (op: %lu), ignore once: %llx "
1549 					"(op: %lu)\n", nubThread->id, threadID, ignore,
1550 						ignoreOp, ignoreOnce, ignoreOnceOp));
1551 
1552 				// set the masks
1553 				cpu_status state = disable_interrupts();
1554 				GRAB_THREAD_LOCK();
1555 
1556 				struct thread *thread
1557 					= thread_get_thread_struct_locked(threadID);
1558 				if (thread
1559 					&& thread->team == thread_get_current_thread()->team) {
1560 					thread_debug_info &threadDebugInfo = thread->debug_info;
1561 					// set ignore mask
1562 					switch (ignoreOp) {
1563 						case B_DEBUG_SIGNAL_MASK_AND:
1564 							threadDebugInfo.ignore_signals &= ignore;
1565 							break;
1566 						case B_DEBUG_SIGNAL_MASK_OR:
1567 							threadDebugInfo.ignore_signals |= ignore;
1568 							break;
1569 						case B_DEBUG_SIGNAL_MASK_SET:
1570 							threadDebugInfo.ignore_signals = ignore;
1571 							break;
1572 					}
1573 
1574 					// set ignore once mask
1575 					switch (ignoreOnceOp) {
1576 						case B_DEBUG_SIGNAL_MASK_AND:
1577 							threadDebugInfo.ignore_signals_once &= ignoreOnce;
1578 							break;
1579 						case B_DEBUG_SIGNAL_MASK_OR:
1580 							threadDebugInfo.ignore_signals_once |= ignoreOnce;
1581 							break;
1582 						case B_DEBUG_SIGNAL_MASK_SET:
1583 							threadDebugInfo.ignore_signals_once = ignoreOnce;
1584 							break;
1585 					}
1586 				}
1587 
1588 				RELEASE_THREAD_LOCK();
1589 				restore_interrupts(state);
1590 
1591 				break;
1592 			}
1593 
1594 			case B_DEBUG_MESSAGE_GET_SIGNAL_MASKS:
1595 			{
1596 				// get the parameters
1597 				replyPort = message.get_signal_masks.reply_port;
1598 				thread_id threadID = message.get_signal_masks.thread;
1599 				status_t result = B_OK;
1600 
1601 				// get the masks
1602 				uint64 ignore = 0;
1603 				uint64 ignoreOnce = 0;
1604 
1605 				cpu_status state = disable_interrupts();
1606 				GRAB_THREAD_LOCK();
1607 
1608 				struct thread *thread
1609 					= thread_get_thread_struct_locked(threadID);
1610 				if (thread) {
1611 					ignore = thread->debug_info.ignore_signals;
1612 					ignoreOnce = thread->debug_info.ignore_signals_once;
1613 				} else
1614 					result = B_BAD_THREAD_ID;
1615 
1616 				RELEASE_THREAD_LOCK();
1617 				restore_interrupts(state);
1618 
1619 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_SIGNAL_MASKS: "
1620 					"reply port: %ld, thread: %ld, ignore: %llx, "
1621 					"ignore once: %llx, result: %lx\n", nubThread->id,
1622 					replyPort, threadID, ignore, ignoreOnce, result));
1623 
1624 				// prepare the message
1625 				reply.get_signal_masks.error = result;
1626 				reply.get_signal_masks.ignore_mask = ignore;
1627 				reply.get_signal_masks.ignore_once_mask = ignoreOnce;
1628 				replySize = sizeof(reply.get_signal_masks);
1629 				sendReply = true;
1630 				break;
1631 			}
1632 
1633 			case B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER:
1634 			{
1635 				// get the parameters
1636 				thread_id threadID = message.set_signal_handler.thread;
1637 				int signal = message.set_signal_handler.signal;
1638 				struct sigaction &handler = message.set_signal_handler.handler;
1639 
1640 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER: "
1641 					"thread: %ld, signal: %d, handler: %p\n", nubThread->id,
1642 					threadID, signal, handler.sa_handler));
1643 
1644 				// check, if the thread exists and is ours
1645 				cpu_status state = disable_interrupts();
1646 				GRAB_THREAD_LOCK();
1647 
1648 				struct thread *thread
1649 					= thread_get_thread_struct_locked(threadID);
1650 				if (thread
1651 					&& thread->team != thread_get_current_thread()->team) {
1652 					thread = NULL;
1653 				}
1654 
1655 				RELEASE_THREAD_LOCK();
1656 				restore_interrupts(state);
1657 
1658 				// set the handler
1659 				if (thread)
1660 					sigaction_etc(threadID, signal, &handler, NULL);
1661 
1662 				break;
1663 			}
1664 
1665 			case B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER:
1666 			{
1667 				// get the parameters
1668 				replyPort = message.get_signal_handler.reply_port;
1669 				thread_id threadID = message.get_signal_handler.thread;
1670 				int signal = message.get_signal_handler.signal;
1671 				status_t result = B_OK;
1672 
1673 				// check, if the thread exists and is ours
1674 				cpu_status state = disable_interrupts();
1675 				GRAB_THREAD_LOCK();
1676 
1677 				struct thread *thread
1678 					= thread_get_thread_struct_locked(threadID);
1679 				if (thread) {
1680 					if (thread->team != thread_get_current_thread()->team)
1681 						result = B_BAD_VALUE;
1682 				} else
1683 					result = B_BAD_THREAD_ID;
1684 
1685 				RELEASE_THREAD_LOCK();
1686 				restore_interrupts(state);
1687 
1688 				// get the handler
1689 				if (result == B_OK) {
1690 					result = sigaction_etc(threadID, signal, NULL,
1691 						&reply.get_signal_handler.handler);
1692 				}
1693 
1694 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER: "
1695 					"reply port: %ld, thread: %ld, signal: %d, "
1696 					"handler: %p\n", nubThread->id, replyPort,
1697 					threadID, signal,
1698 					reply.get_signal_handler.handler.sa_handler));
1699 
1700 				// prepare the message
1701 				reply.get_signal_handler.error = result;
1702 				replySize = sizeof(reply.get_signal_handler);
1703 				sendReply = true;
1704 				break;
1705 			}
1706 
1707 			case B_DEBUG_MESSAGE_PREPARE_HANDOVER:
1708 			{
1709 				TRACE(("nub thread %ld: B_DEBUG_MESSAGE_PREPARE_HANDOVER\n",
1710 					nubThread->id));
1711 
1712 				struct team *team = nubThread->team;
1713 
1714 				// Acquire the debugger write lock. As soon as we have it and
1715 				// have set the B_TEAM_DEBUG_DEBUGGER_HANDOVER flag, no thread
1716 				// will write anything to the debugger port anymore.
1717 				status_t result = acquire_sem_etc(writeLock, 1,
1718 					B_KILL_CAN_INTERRUPT, 0);
1719 				if (result == B_OK) {
1720 					// set the respective team debug flag
1721 					cpu_status state = disable_interrupts();
1722 					GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1723 
1724 					atomic_or(&team->debug_info.flags,
1725 						B_TEAM_DEBUG_DEBUGGER_HANDOVER);
1726 
1727 					RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1728 					restore_interrupts(state);
1729 
1730 					release_sem(writeLock);
1731 				} else {
1732 					// We probably got a SIGKILL. If so, we will terminate when
1733 					// reading the next message fails.
1734 				}
1735 
1736 				break;
1737 			}
1738 
1739 			case B_DEBUG_MESSAGE_HANDED_OVER:
1740 			{
1741 				// notify all threads that the debugger has changed
1742 				broadcast_debugged_thread_message(nubThread,
1743 					B_DEBUGGED_THREAD_DEBUGGER_CHANGED, NULL, 0);
1744 
1745 				break;
1746 			}
1747 		}
1748 
1749 		// send the reply, if necessary
1750 		if (sendReply) {
1751 			status_t error = kill_interruptable_write_port(replyPort, command,
1752 				&reply, replySize);
1753 
1754 			if (error != B_OK) {
1755 				// The debugger port is either not longer existing or we got
1756 				// interrupted by a kill signal. In either case we terminate.
1757 				TRACE(("nub thread %ld: failed to send reply to port %ld: %s\n",
1758 					nubThread->id, replyPort, strerror(error)));
1759 
1760 				nub_thread_cleanup(nubThread);
1761 				return error;
1762 			}
1763 		}
1764 	}
1765 }
1766 
1767 
1768 /**	\brief Helper function for install_team_debugger(), that sets up the team
1769  *		   and thread debug infos.
1770  *
1771  *	Interrupts must be enabled and the team debug info lock of the team to be
1772  *	debugged must be held. The function will release the lock, but leave
1773  *	interrupts disabled.
1774  */
1775 static void
1776 install_team_debugger_init_debug_infos(struct team *team, team_id debuggerTeam,
1777 	port_id debuggerPort, port_id nubPort, thread_id nubThread,
1778 	sem_id debuggerPortWriteLock)
1779 {
1780 	atomic_set(&team->debug_info.flags,
1781 		B_TEAM_DEBUG_DEFAULT_FLAGS | B_TEAM_DEBUG_DEBUGGER_INSTALLED);
1782 	team->debug_info.nub_port = nubPort;
1783 	team->debug_info.nub_thread = nubThread;
1784 	team->debug_info.debugger_team = debuggerTeam;
1785 	team->debug_info.debugger_port = debuggerPort;
1786 	team->debug_info.debugger_write_lock = debuggerPortWriteLock;
1787 
1788 	RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1789 
1790 	// set the user debug flags and signal masks of all threads to the default
1791 	GRAB_THREAD_LOCK();
1792 
1793 	for (struct thread *thread = team->thread_list;
1794 		 thread;
1795 		 thread = thread->team_next) {
1796 		if (thread->id != nubThread) {
1797 			int32 flags = thread->debug_info.flags
1798 				& ~B_THREAD_DEBUG_USER_FLAG_MASK;
1799 			atomic_set(&thread->debug_info.flags,
1800 				flags | B_THREAD_DEBUG_DEFAULT_FLAGS);
1801 			thread->debug_info.ignore_signals = 0;
1802 			thread->debug_info.ignore_signals_once = 0;
1803 		}
1804 	}
1805 
1806 	RELEASE_THREAD_LOCK();
1807 }
1808 
1809 
1810 static port_id
1811 install_team_debugger(team_id teamID, port_id debuggerPort, bool useDefault,
1812 	bool dontFail)
1813 {
1814 	TRACE(("install_team_debugger(team: %ld, port: %ld, default: %d, "
1815 		"dontFail: %d)\n", teamID, debuggerPort, useDefault, dontFail));
1816 
1817 	if (useDefault)
1818 		debuggerPort = atomic_get(&sDefaultDebuggerPort);
1819 
1820 	// get the debugger team
1821 	port_info debuggerPortInfo;
1822 	status_t error = get_port_info(debuggerPort, &debuggerPortInfo);
1823 	if (error != B_OK) {
1824 		TRACE(("install_team_debugger(): Failed to get debugger port info: "
1825 			"%lx\n", error));
1826 		return error;
1827 	}
1828 	team_id debuggerTeam = debuggerPortInfo.team;
1829 
1830 	// check the debugger team: It must neither be the kernel team nor the
1831 	// debugged team
1832 	if (debuggerTeam == team_get_kernel_team_id() || debuggerTeam == teamID) {
1833 		TRACE(("install_team_debugger(): Can't debug kernel or debugger team. "
1834 			"debugger: %ld, debugged: %ld\n", debuggerTeam, teamID));
1835 		return B_NOT_ALLOWED;
1836 	}
1837 
1838 	// check, if a debugger is already installed
1839 
1840 	bool done = false;
1841 	port_id result = B_ERROR;
1842 	bool handOver = false;
1843 	bool releaseDebugInfoLock = true;
1844 	port_id oldDebuggerPort = -1;
1845 	port_id nubPort = -1;
1846 
1847 	cpu_status state = disable_interrupts();
1848 	GRAB_TEAM_LOCK();
1849 
1850 	// get a real team ID
1851 	// We look up the team by ID, even in case of the current team, so we can be
1852 	// sure, that the team is not already dying.
1853 	if (teamID == B_CURRENT_TEAM)
1854 		teamID = thread_get_current_thread()->team->id;
1855 
1856 	struct team *team = team_get_team_struct_locked(teamID);
1857 
1858 	if (team) {
1859 		GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1860 
1861 		int32 teamDebugFlags = team->debug_info.flags;
1862 
1863 		if (team == team_get_kernel_team()) {
1864 			// don't allow to debug the kernel
1865 			error = B_NOT_ALLOWED;
1866 		} else if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
1867 			if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_HANDOVER) {
1868 				// a handover to another debugger is requested
1869 				// clear the flag
1870 				atomic_and(& team->debug_info.flags,
1871 					~B_TEAM_DEBUG_DEBUGGER_HANDOVER);
1872 
1873 				oldDebuggerPort = team->debug_info.debugger_port;
1874 				result = nubPort = team->debug_info.nub_port;
1875 
1876 				// set the new debugger
1877 				install_team_debugger_init_debug_infos(team, debuggerTeam,
1878 					debuggerPort, nubPort, team->debug_info.nub_thread,
1879 					team->debug_info.debugger_write_lock);
1880 
1881 				releaseDebugInfoLock = false;
1882 				handOver = true;
1883 				done = true;
1884 
1885 				// finally set the new port owner
1886 				if (set_port_owner(nubPort, debuggerTeam) != B_OK) {
1887 					// The old debugger must just have died. Just proceed as
1888 					// if there was no debugger installed. We may still be too
1889 					// early, in which case we'll fail, but this race condition
1890 					// should be unbelievably rare and relatively harmless.
1891 					handOver = false;
1892 					done = false;
1893 				}
1894 
1895 			} else {
1896 				// there's already a debugger installed
1897 				error = (dontFail ? B_OK : B_BAD_VALUE);
1898 				done = true;
1899 				result = team->debug_info.nub_port;
1900 			}
1901 		}
1902 
1903 		// in case of a handover the lock has already been released
1904 		if (releaseDebugInfoLock)
1905 			RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1906 	} else
1907 		error = B_BAD_TEAM_ID;
1908 
1909 	RELEASE_TEAM_LOCK();
1910 	restore_interrupts(state);
1911 
1912 	if (handOver) {
1913 		// notify the nub thread
1914 		kill_interruptable_write_port(nubPort, B_DEBUG_MESSAGE_HANDED_OVER,
1915 			NULL, 0);
1916 
1917 		// notify the old debugger
1918 		debug_handed_over notification;
1919 		notification.origin.thread = -1;
1920 		notification.origin.team = teamID;
1921 		notification.origin.nub_port = nubPort;
1922 		notification.debugger = debuggerTeam;
1923 		notification.debugger_port = debuggerPort;
1924 
1925 		error = write_port_etc(oldDebuggerPort,
1926 			B_DEBUGGER_MESSAGE_HANDED_OVER, &notification,
1927 			sizeof(notification), B_RELATIVE_TIMEOUT, 0);
1928 		if (error != B_OK) {
1929 			TRACE(("install_team_debugger(): Failed to send message to old "
1930 				"debugger: %s\n", strerror(error)));
1931 		}
1932 
1933 		TRACE(("install_team_debugger() done: handed over to debugger: team: "
1934 			"%ld, port: %ld\n", debuggerTeam, debuggerPort));
1935 
1936 		return result;
1937 	}
1938 
1939 	if (done || error != B_OK) {
1940 		TRACE(("install_team_debugger() done1: %ld\n",
1941 			(error == B_OK ? result : error)));
1942 		return (error == B_OK ? result : error);
1943 	}
1944 
1945 	// create the debugger write lock semaphore
1946 	char nameBuffer[B_OS_NAME_LENGTH];
1947 	snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debugger port write",
1948 		teamID);
1949 	sem_id debuggerWriteLock = create_sem(1, nameBuffer);
1950 	if (debuggerWriteLock < 0)
1951 		error = debuggerWriteLock;
1952 
1953 	// create the nub port
1954 	snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug", teamID);
1955 	if (error == B_OK) {
1956 		nubPort = create_port(1, nameBuffer);
1957 		if (nubPort < 0)
1958 			error = nubPort;
1959 		else
1960 			result = nubPort;
1961 	}
1962 
1963 	// make the debugger team the port owner; thus we know, if the debugger is
1964 	// gone and can cleanup
1965 	if (error == B_OK)
1966 		error = set_port_owner(nubPort, debuggerTeam);
1967 
1968 	// spawn the nub thread
1969 	thread_id nubThread = -1;
1970 	if (error == B_OK) {
1971 		snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug task", teamID);
1972 		nubThread = spawn_kernel_thread_etc(debug_nub_thread, nameBuffer,
1973 			B_NORMAL_PRIORITY, NULL, teamID, -1);
1974 		if (nubThread < 0)
1975 			error = nubThread;
1976 	}
1977 
1978 	// now adjust the debug info accordingly
1979 	if (error == B_OK) {
1980 		state = disable_interrupts();
1981 		GRAB_TEAM_LOCK();
1982 
1983 		// look up again, to make sure the team isn't dying
1984 		team = team_get_team_struct_locked(teamID);
1985 
1986 		if (team) {
1987 			GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1988 
1989 			if (team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
1990 				// there's already a debugger installed
1991 				error = (dontFail ? B_OK : B_BAD_VALUE);
1992 				done = true;
1993 				result = team->debug_info.nub_port;
1994 
1995 				RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
1996 			} else {
1997 				install_team_debugger_init_debug_infos(team, debuggerTeam,
1998 					debuggerPort, nubPort, nubThread, debuggerWriteLock);
1999 			}
2000 		} else
2001 			error = B_BAD_TEAM_ID;
2002 
2003 		RELEASE_TEAM_LOCK();
2004 		restore_interrupts(state);
2005 	}
2006 
2007 	// if everything went fine, resume the nub thread, otherwise clean up
2008 	if (error == B_OK && !done) {
2009 		resume_thread(nubThread);
2010 	} else {
2011 		// delete port and terminate thread
2012 		if (nubPort >= 0) {
2013 			set_port_owner(nubPort, B_CURRENT_TEAM);
2014 			delete_port(nubPort);
2015 		}
2016 		if (nubThread >= 0) {
2017 			int32 result;
2018 			wait_for_thread(nubThread, &result);
2019 		}
2020 	}
2021 
2022 	TRACE(("install_team_debugger() done2: %ld\n",
2023 		(error == B_OK ? result : error)));
2024 	return (error == B_OK ? result : error);
2025 }
2026 
2027 
2028 static status_t
2029 ensure_debugger_installed(team_id teamID, port_id *_port)
2030 {
2031 	port_id port = install_team_debugger(teamID, -1, true, true);
2032 	if (port < 0)
2033 		return port;
2034 
2035 	if (_port)
2036 		*_port = port;
2037 	return B_OK;
2038 }
2039 
2040 
2041 // #pragma mark -
2042 
2043 
2044 void
2045 _user_debugger(const char *userMessage)
2046 {
2047 	// install the default debugger, if there is none yet
2048 	struct thread *thread = thread_get_current_thread();
2049 	port_id nubPort;
2050 	status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort);
2051 	if (error != B_OK) {
2052 		// time to commit suicide
2053 		char buffer[128];
2054 		ssize_t length = user_strlcpy(buffer, userMessage, sizeof(buffer));
2055 		if (length >= 0) {
2056 			dprintf("_user_debugger(): Failed to install debugger. Message is: "
2057 				"`%s'\n", buffer);
2058 		} else {
2059 			dprintf("_user_debugger(): Failed to install debugger. Message is: "
2060 				"%p (%s)\n", userMessage, strerror(length));
2061 		}
2062 		_user_exit_team(1);
2063 	}
2064 
2065 	// prepare the message
2066 	debug_debugger_call message;
2067 	message.message = (void*)userMessage;
2068 
2069 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_DEBUGGER_CALL, &message,
2070 		sizeof(message), true);
2071 }
2072 
2073 
2074 int
2075 _user_disable_debugger(int state)
2076 {
2077 	struct team *team = thread_get_current_thread()->team;
2078 
2079 	cpu_status cpuState = disable_interrupts();
2080 	GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
2081 
2082 	int32 oldFlags;
2083 	if (state)
2084 		oldFlags = atomic_and(&team->debug_info.flags, ~B_TEAM_DEBUG_SIGNALS);
2085 	else
2086 		oldFlags = atomic_or(&team->debug_info.flags, B_TEAM_DEBUG_SIGNALS);
2087 
2088 	RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
2089 	restore_interrupts(cpuState);
2090 
2091 	// TODO: Check, if the return value is really the old state.
2092 	return !(oldFlags & B_TEAM_DEBUG_SIGNALS);
2093 }
2094 
2095 
2096 status_t
2097 _user_install_default_debugger(port_id debuggerPort)
2098 {
2099 	// if supplied, check whether the port is a valid port
2100 	if (debuggerPort >= 0) {
2101 		port_info portInfo;
2102 		status_t error = get_port_info(debuggerPort, &portInfo);
2103 		if (error != B_OK)
2104 			return error;
2105 
2106 		// the debugger team must not be the kernel team
2107 		if (portInfo.team == team_get_kernel_team_id())
2108 			return B_NOT_ALLOWED;
2109 	}
2110 
2111 	atomic_set(&sDefaultDebuggerPort, debuggerPort);
2112 
2113 	return B_OK;
2114 }
2115 
2116 
2117 port_id
2118 _user_install_team_debugger(team_id teamID, port_id debuggerPort)
2119 {
2120 	return install_team_debugger(teamID, debuggerPort, false, false);
2121 }
2122 
2123 
2124 status_t
2125 _user_remove_team_debugger(team_id teamID)
2126 {
2127 	struct team_debug_info info;
2128 
2129 	status_t error = B_OK;
2130 
2131 	cpu_status state = disable_interrupts();
2132 	GRAB_TEAM_LOCK();
2133 
2134 	struct team *team = (teamID == B_CURRENT_TEAM
2135 		? thread_get_current_thread()->team
2136 		: team_get_team_struct_locked(teamID));
2137 
2138 	if (team) {
2139 		GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
2140 
2141 		if (team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {
2142 			// there's a debugger installed
2143 			info = team->debug_info;
2144 			clear_team_debug_info(&team->debug_info, false);
2145 		} else {
2146 			// no debugger installed
2147 			error = B_BAD_VALUE;
2148 		}
2149 
2150 		RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);
2151 	} else
2152 		error = B_BAD_TEAM_ID;
2153 
2154 	RELEASE_TEAM_LOCK();
2155 	restore_interrupts(state);
2156 
2157 	// clean up the info, if there was a debugger installed
2158 	if (error == B_OK)
2159 		destroy_team_debug_info(&info);
2160 
2161 	return error;
2162 }
2163 
2164 
2165 status_t
2166 _user_debug_thread(thread_id threadID)
2167 {
2168 	// tell the thread to stop as soon as possible
2169 	status_t error = B_OK;
2170 	cpu_status state = disable_interrupts();
2171 	GRAB_THREAD_LOCK();
2172 
2173 	struct thread *thread = thread_get_thread_struct_locked(threadID);
2174 	if (!thread) {
2175 		// thread doesn't exist any longer
2176 		error = B_BAD_THREAD_ID;
2177 	} else if (thread->team == team_get_kernel_team()) {
2178 		// we can't debug the kernel team
2179 		error = B_NOT_ALLOWED;
2180 	} else if (thread->debug_info.flags & B_THREAD_DEBUG_DYING) {
2181 		// the thread is already dying -- too late to debug it
2182 		error = B_BAD_THREAD_ID;
2183 	} else if (!(thread->debug_info.flags & B_THREAD_DEBUG_STOPPED)) {
2184 		// set the flag that tells the thread to stop as soon as possible
2185 		atomic_or(&thread->debug_info.flags, B_THREAD_DEBUG_STOP);
2186 
2187 		switch (thread->state) {
2188 			case B_THREAD_SUSPENDED:
2189 				// thread suspended: wake it up
2190 				thread->state = thread->next_state = B_THREAD_READY;
2191 				scheduler_enqueue_in_run_queue(thread);
2192 				break;
2193 
2194 			case B_THREAD_WAITING:
2195 				// thread waiting: interrupt it
2196 				sem_interrupt_thread(thread);
2197 				break;
2198 		}
2199 	}
2200 
2201 	RELEASE_THREAD_LOCK();
2202 	restore_interrupts(state);
2203 
2204 	return error;
2205 }
2206 
2207 void
2208 _user_wait_for_debugger(void)
2209 {
2210 	debug_thread_debugged message;
2211 	thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, &message,
2212 		sizeof(message), false);
2213 }
2214 
2215 
2216