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