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