1bc797a9eSIngo Weinhold/*
24535495dSIngo Weinhold * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3bc797a9eSIngo Weinhold * Distributed under the terms of the MIT License.
4bc797a9eSIngo Weinhold *
5bc797a9eSIngo Weinhold * Userland debugger support.
6bc797a9eSIngo Weinhold */
7bc797a9eSIngo Weinhold#ifndef _KERNEL_USER_DEBUGGER_H
8bc797a9eSIngo Weinhold#define _KERNEL_USER_DEBUGGER_H
9bc797a9eSIngo Weinhold
10ac106be5SIngo Weinhold
11e988d660SIngo Weinhold#include <debugger.h>
12bc797a9eSIngo Weinhold
13a7ad39feSIngo Weinhold#include <arch/user_debugger.h>
14a7ad39feSIngo Weinhold
15cbcebd33SIngo Weinhold#include <timer.h>
16cbcebd33SIngo Weinhold
17cbcebd33SIngo Weinhold
18cbcebd33SIngo Weinhold// limits
19ab30ce0eSIngo Weinhold#define B_DEBUG_MIN_PROFILE_INTERVAL			10			/* in us */
200135e2e3SIngo Weinhold#define B_DEBUG_STACK_TRACE_DEPTH				128
21ecfad924SIngo Weinhold#define	B_DEBUG_PROFILE_BUFFER_FLUSH_THRESHOLD	70			/* in % */
22cbcebd33SIngo Weinhold
23cbcebd33SIngo Weinhold
24b0f12d64SIngo Weinholdstruct BreakpointManager;
25ba391bccSIngo Weinholdstruct ConditionVariable;
26cbcebd33SIngo Weinholdstruct function_profile_info;
274535495dSIngo Weinhold
284535495dSIngo Weinholdnamespace BKernel {
294535495dSIngo Weinhold	struct Thread;
304535495dSIngo Weinhold}
314535495dSIngo Weinhold
324535495dSIngo Weinholdusing BKernel::Thread;
334535495dSIngo Weinhold
34cbcebd33SIngo Weinhold
35a7ad39feSIngo Weinhold// Team related debugging data.
36a7ad39feSIngo Weinhold//
37a7ad39feSIngo Weinhold// Locking policy:
38a7ad39feSIngo Weinhold// 1) When accessing the structure it must be made sure, that the structure,
3924df6592SIngo Weinhold//    (i.e. the struct Team it lives in) isn't deleted. Thus one either needs to
4024df6592SIngo Weinhold//    get a team reference, lock the team, or one accesses the structure from a
4124df6592SIngo Weinhold//    thread of that team.
42ac106be5SIngo Weinhold// 2) Access to the `flags' field is atomic. Reading via atomic_get()
43a7ad39feSIngo Weinhold//    requires no further locks (in addition to 1) that is). Writing requires
4424df6592SIngo Weinhold//    `lock' to be held and must be done atomically, too
45a7ad39feSIngo Weinhold//    (atomic_{set,and,or}()). Reading with `lock' being held doesn't need to
46a7ad39feSIngo Weinhold//    be done atomically.
4724df6592SIngo Weinhold// 3) Access to all other fields (read or write) requires `lock' to be held.
4824df6592SIngo Weinhold// 4) Locking order is scheduler lock -> Team -> Thread -> team_debug_info::lock
4924df6592SIngo Weinhold//    -> thread_debug_info::lock.
50a7ad39feSIngo Weinhold//
51bc797a9eSIngo Weinholdstruct team_debug_info {
52a7ad39feSIngo Weinhold	spinlock	lock;
53a7ad39feSIngo Weinhold		// Guards the remaining fields. Should always be the innermost lock
5424df6592SIngo Weinhold		// to be acquired/released, save for thread_debug_info::lock.
55a7ad39feSIngo Weinhold
56bc797a9eSIngo Weinhold	int32		flags;
5724df6592SIngo Weinhold		// Set atomically. So reading atomically is OK, even when the lock is
5824df6592SIngo Weinhold		// not held (at least if it is certain, that the team struct won't go).
59a7ad39feSIngo Weinhold
60bc797a9eSIngo Weinhold	team_id		debugger_team;
61bc797a9eSIngo Weinhold	port_id		debugger_port;
62bc797a9eSIngo Weinhold	thread_id	nub_thread;
63bc797a9eSIngo Weinhold	port_id		nub_port;
64bc797a9eSIngo Weinhold		// the port the nub thread is waiting on for commands from the debugger
652eece863SIngo Weinhold	sem_id		debugger_write_lock;
662eece863SIngo Weinhold		// synchronizes writes to the debugger port with the setting (but not
672eece863SIngo Weinhold		// clearing) of the B_TEAM_DEBUG_DEBUGGER_HANDOVER flag
68e1975d33SIngo Weinhold	thread_id	causing_thread;
69e1975d33SIngo Weinhold		// thread that caused the debugger to be attached; -1 for manual
70e1975d33SIngo Weinhold		// debugger attachment (or no debugger installed)
7173ad2473SPawel Dziepak	int32		image_event;
72eba9a4c3SIngo Weinhold		// counter incremented whenever an image is created/deleted
73a7ad39feSIngo Weinhold
74ba391bccSIngo Weinhold	struct ConditionVariable* debugger_changed_condition;
7524df6592SIngo Weinhold		// Set to a condition variable when going to change the debugger. Anyone
7624df6592SIngo Weinhold		// who wants to change the debugger as well, needs to wait until the
7724df6592SIngo Weinhold		// condition variable is unset again (waiting for the condition and
7824df6592SIngo Weinhold		// rechecking again). The field and the condition variable is protected
7924df6592SIngo Weinhold		// by 'lock'. After setting the a condition variable the team is
8024df6592SIngo Weinhold		// guaranteed not to be deleted (until it is unset) it might be removed
8124df6592SIngo Weinhold		// from the team hash table, though.
82ba391bccSIngo Weinhold
83b0f12d64SIngo Weinhold	struct BreakpointManager* breakpoint_manager;
84b0f12d64SIngo Weinhold		// manages hard- and software breakpoints
85b0f12d64SIngo Weinhold
86a7ad39feSIngo Weinhold	struct arch_team_debug_info	arch_info;
87bc797a9eSIngo Weinhold};
88bc797a9eSIngo Weinhold
8924df6592SIngo Weinhold// Thread related debugging data.
9024df6592SIngo Weinhold//
9124df6592SIngo Weinhold// Locking policy:
9224df6592SIngo Weinhold// 1) When accessing the structure it must be made sure, that the structure,
9324df6592SIngo Weinhold//    (i.e. the struct Thread it lives in) isn't deleted. Thus one either needs
9424df6592SIngo Weinhold//    to get a thread reference, lock the thread, or one accesses the structure
9524df6592SIngo Weinhold//    of the current thread.
9624df6592SIngo Weinhold// 2) Access to the `flags' field is atomic. Reading via atomic_get()
9724df6592SIngo Weinhold//    requires no further locks (in addition to 1) that is). Writing requires
9824df6592SIngo Weinhold//    `lock' to be held and must be done atomically, too
9924df6592SIngo Weinhold//    (atomic_{set,and,or}()). Reading with `lock' being held doesn't need to
10024df6592SIngo Weinhold//    be done atomically.
10124df6592SIngo Weinhold// 3) Access to all other fields (read or write) requires `lock' to be held.
10224df6592SIngo Weinhold// 4) Locking order is scheduler lock -> Team -> Thread -> team_debug_info::lock
10324df6592SIngo Weinhold//    -> thread_debug_info::lock.
10424df6592SIngo Weinhold//
105bc797a9eSIngo Weinholdstruct thread_debug_info {
10624df6592SIngo Weinhold	spinlock	lock;
10724df6592SIngo Weinhold		// Guards the remaining fields. Should always be the innermost lock
10824df6592SIngo Weinhold		// to be acquired/released.
10924df6592SIngo Weinhold
110bc797a9eSIngo Weinhold	int32		flags;
11124df6592SIngo Weinhold		// Set atomically. So reading atomically is OK, even when the lock is
11224df6592SIngo Weinhold		// not held (at least if it is certain, that the thread struct won't
11324df6592SIngo Weinhold		// go).
114bc797a9eSIngo Weinhold	port_id		debug_port;
115bc797a9eSIngo Weinhold		// the port the thread is waiting on for commands from the nub thread
116ae7c619aSIngo Weinhold
11750374cbdSAxel Dörfler	sigset_t	ignore_signals;
118293a59b0SIngo Weinhold		// the signals the debugger is not interested in
11950374cbdSAxel Dörfler	sigset_t	ignore_signals_once;
120293a59b0SIngo Weinhold		// the signals the debugger wishes not to be notified of, when they
121293a59b0SIngo Weinhold		// occur the next time
122293a59b0SIngo Weinhold
123424f833bSIngo Weinhold	// profiling related part; if samples != NULL, the thread is profiled
124cbcebd33SIngo Weinhold	struct {
125424f833bSIngo Weinhold		bigtime_t		interval;
126cbcebd33SIngo Weinhold			// sampling interval
127424f833bSIngo Weinhold		area_id			sample_area;
128424f833bSIngo Weinhold			// cloned sample buffer area
129424f833bSIngo Weinhold		addr_t*			samples;
130424f833bSIngo Weinhold			// sample buffer
131424f833bSIngo Weinhold		int32			max_samples;
132424f833bSIngo Weinhold			// maximum number of samples the buffer can hold
133ecfad924SIngo Weinhold		int32			flush_threshold;
134ecfad924SIngo Weinhold			// number of sample when the buffer is flushed (if possible)
135424f833bSIngo Weinhold		int32			sample_count;
136424f833bSIngo Weinhold			// number of samples the buffer currently holds
137424f833bSIngo Weinhold		int32			stack_depth;
138424f833bSIngo Weinhold			// number of return addresses to record per timer interval
139ecfad924SIngo Weinhold		int32			dropped_ticks;
140ecfad924SIngo Weinhold			// number of ticks that had to be dropped when the sample buffer was
141ecfad924SIngo Weinhold			// full and couldn't be flushed
142eba9a4c3SIngo Weinhold		int32			image_event;
143eba9a4c3SIngo Weinhold			// number of the image event when the first sample was written into
144eba9a4c3SIngo Weinhold			// the buffer
145f965a969SIngo Weinhold		int32			last_image_event;
146f965a969SIngo Weinhold			// number of the image event when the last sample was written into
147f965a969SIngo Weinhold			// the buffer
1480135e2e3SIngo Weinhold		bool			variable_stack_depth;
1490135e2e3SIngo Weinhold			// record a variable number of samples per hit
15078b13af6SIngo Weinhold		bool			buffer_full;
15178b13af6SIngo Weinhold			// indicates that the sample buffer is full
152cbcebd33SIngo Weinhold		union {
153424f833bSIngo Weinhold			bigtime_t	interval_left;
154cbcebd33SIngo Weinhold				// when unscheduled: the time left of the current sampling
155cbcebd33SIngo Weinhold				// interval
156424f833bSIngo Weinhold			bigtime_t	timer_end;
157cbcebd33SIngo Weinhold				// when running: the absolute time the timer is supposed to go
158cbcebd33SIngo Weinhold				// off
159cbcebd33SIngo Weinhold		};
160424f833bSIngo Weinhold		timer*			installed_timer;
161cbcebd33SIngo Weinhold			// when running and being profiled: the CPU's profiling timer
162cbcebd33SIngo Weinhold	} profile;
163cbcebd33SIngo Weinhold
164ae7c619aSIngo Weinhold	struct arch_thread_debug_info	arch_info;
165bc797a9eSIngo Weinhold};
166bc797a9eSIngo Weinhold
167a7ad39feSIngo Weinhold#define GRAB_TEAM_DEBUG_INFO_LOCK(info)		acquire_spinlock(&(info).lock)
168a7ad39feSIngo Weinhold#define RELEASE_TEAM_DEBUG_INFO_LOCK(info)	release_spinlock(&(info).lock)
169a7ad39feSIngo Weinhold
170bc797a9eSIngo Weinhold// team debugging flags (user-specifiable flags are in <debugger.h>)
171bc797a9eSIngo Weinholdenum {
172e1975d33SIngo Weinhold	B_TEAM_DEBUG_DEBUGGER_INSTALLED		= 0x0001,
173e1975d33SIngo Weinhold	B_TEAM_DEBUG_DEBUGGER_HANDOVER		= 0x0002,	// marked for hand-over
174e1975d33SIngo Weinhold	B_TEAM_DEBUG_DEBUGGER_HANDING_OVER	= 0x0004,	// handing over
175e1975d33SIngo Weinhold	B_TEAM_DEBUG_DEBUGGER_DISABLED		= 0x0008,
176bc797a9eSIngo Weinhold
177e1975d33SIngo Weinhold	B_TEAM_DEBUG_KERNEL_FLAG_MASK		= 0xffff,
178e988d660SIngo Weinhold
179e1975d33SIngo Weinhold	B_TEAM_DEBUG_DEFAULT_FLAGS			= 0,
181bc797a9eSIngo Weinhold};
182bc797a9eSIngo Weinhold
183bc797a9eSIngo Weinhold// thread debugging flags (user-specifiable flags are in <debugger.h>)
184bc797a9eSIngo Weinholdenum {
1858b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_INITIALIZED			= 0x0001,
1868b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_DYING				= 0x0002,
1878b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_STOP					= 0x0004,
1888b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_STOPPED				= 0x0008,
1898b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_SINGLE_STEP			= 0x0010,
1908b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_NOTIFY_SINGLE_STEP	= 0x0020,
191bc797a9eSIngo Weinhold
1928b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_NUB_THREAD			= 0x0040,	// marks the nub thread
19337a25a6cSIngo Weinhold
1948b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_KERNEL_FLAG_MASK		= 0xffff,
195e988d660SIngo Weinhold
1968b3d3d8aSIngo Weinhold	B_THREAD_DEBUG_DEFAULT_FLAGS		= 0,
197bc797a9eSIngo Weinhold};
198bc797a9eSIngo Weinhold
199bc797a9eSIngo Weinhold// messages sent from the debug nub thread to a debugged thread
200e988d660SIngo Weinholdtypedef enum {
202a7ad39feSIngo Weinhold	B_DEBUGGED_THREAD_SET_CPU_STATE,
203823f4c5bSIngo Weinhold	B_DEBUGGED_THREAD_GET_CPU_STATE,
205bc797a9eSIngo Weinhold} debugged_thread_message;
206bc797a9eSIngo Weinhold
207e988d660SIngo Weinholdtypedef struct {
208e988d660SIngo Weinhold	uint32	handle_event;
209a7ad39feSIngo Weinhold	bool	single_step;
210a7ad39feSIngo Weinhold} debugged_thread_continue;
211a7ad39feSIngo Weinhold
2122562e518SIngo Weinholdtypedef struct {
2132562e518SIngo Weinhold	port_id	reply_port;
214823f4c5bSIngo Weinhold} debugged_thread_get_cpu_state;
2152562e518SIngo Weinhold
216a7ad39feSIngo Weinholdtypedef struct {
217a7ad39feSIngo Weinhold	debug_cpu_state	cpu_state;
218a7ad39feSIngo Weinhold} debugged_thread_set_cpu_state;
219e988d660SIngo Weinhold
220e988d660SIngo Weinholdtypedef union {
221a7ad39feSIngo Weinhold	debugged_thread_continue		continue_thread;
222a7ad39feSIngo Weinhold	debugged_thread_set_cpu_state	set_cpu_state;
223823f4c5bSIngo Weinhold	debugged_thread_get_cpu_state	get_cpu_state;
224e988d660SIngo Weinhold} debugged_thread_message_data;
225bc797a9eSIngo Weinhold
226bc797a9eSIngo Weinhold
2272eece863SIngo Weinhold// internal messages sent to the nub thread
2282eece863SIngo Weinholdtypedef enum {
2292eece863SIngo Weinhold	B_DEBUG_MESSAGE_HANDED_OVER		= -1,
2302eece863SIngo Weinhold} debug_nub_kernel_message;
2312eece863SIngo Weinhold
2322eece863SIngo Weinhold
233bc797a9eSIngo Weinhold#ifdef __cplusplus
234bc797a9eSIngo Weinholdextern "C" {
235bc797a9eSIngo Weinhold#endif
236bc797a9eSIngo Weinhold
237bc797a9eSIngo Weinhold// service calls
238bc797a9eSIngo Weinhold
239a7ad39feSIngo Weinholdvoid clear_team_debug_info(struct team_debug_info *info, bool initLock);
240bc797a9eSIngo Weinhold
241cbcebd33SIngo Weinholdvoid init_thread_debug_info(struct thread_debug_info *info);
242cbcebd33SIngo Weinholdvoid clear_thread_debug_info(struct thread_debug_info *info, bool dying);
243bc797a9eSIngo Weinholdvoid destroy_thread_debug_info(struct thread_debug_info *info);
244bc797a9eSIngo Weinhold
2453eae1feaSIngo Weinholdvoid user_debug_prepare_for_exec();
2463eae1feaSIngo Weinholdvoid user_debug_finish_after_exec();
2473eae1feaSIngo Weinhold
2483eae1feaSIngo Weinholdvoid init_user_debug();
249e988d660SIngo Weinhold
25034b3b26bSIngo Weinhold
251e988d660SIngo Weinhold// debug event callbacks
252e988d660SIngo Weinhold
253bc797a9eSIngo Weinholdvoid user_debug_pre_syscall(uint32 syscall, void *args);
254bc797a9eSIngo Weinholdvoid user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
255bc797a9eSIngo Weinhold		bigtime_t startTime);
256293a59b0SIngo Weinholdbool user_debug_exception_occurred(debug_exception_type exception, int signal);
257e988d660SIngo Weinholdbool user_debug_handle_signal(int signal, struct sigaction *handler,
258e988d660SIngo Weinhold		bool deadly);
259bc797a9eSIngo Weinholdvoid user_debug_stop_thread();
260e988d660SIngo Weinholdvoid user_debug_team_created(team_id teamID);
261e988d660SIngo Weinholdvoid user_debug_team_deleted(team_id teamID, port_id debuggerPort);
2624ed8088fSIngo Weinholdvoid user_debug_team_exec();
26324df6592SIngo Weinholdvoid user_debug_update_new_thread_flags(Thread* thread);
264e988d660SIngo Weinholdvoid user_debug_thread_created(thread_id threadID);
265e988d660SIngo Weinholdvoid user_debug_thread_deleted(team_id teamID, thread_id threadID);
2664535495dSIngo Weinholdvoid user_debug_thread_exiting(Thread* thread);
267e988d660SIngo Weinholdvoid user_debug_image_created(const image_info *imageInfo);
268e988d660SIngo Weinholdvoid user_debug_image_deleted(const image_info *imageInfo);
269823f4c5bSIngo Weinholdvoid user_debug_breakpoint_hit(bool software);
270823f4c5bSIngo Weinholdvoid user_debug_watchpoint_hit();
271ae7c619aSIngo Weinholdvoid user_debug_single_stepped();
272bc797a9eSIngo Weinhold
2734535495dSIngo Weinholdvoid user_debug_thread_unscheduled(Thread* thread);
2744535495dSIngo Weinholdvoid user_debug_thread_scheduled(Thread* thread);
275cbcebd33SIngo Weinhold
276bc797a9eSIngo Weinhold
277bc797a9eSIngo Weinhold// syscalls
278bc797a9eSIngo Weinhold
279bc797a9eSIngo Weinholdvoid		_user_debugger(const char *message);
280bc797a9eSIngo Weinholdint			_user_disable_debugger(int state);
281bc797a9eSIngo Weinhold
282bc797a9eSIngo Weinholdstatus_t	_user_install_default_debugger(port_id debuggerPort);
283bc797a9eSIngo Weinholdport_id		_user_install_team_debugger(team_id team, port_id debuggerPort);
284bc797a9eSIngo Weinholdstatus_t	_user_remove_team_debugger(team_id team);
285bc797a9eSIngo Weinholdstatus_t	_user_debug_thread(thread_id thread);
2866bbfd262SIngo Weinholdvoid		_user_wait_for_debugger(void);
287bc797a9eSIngo Weinhold
28844b5d72bSIngo Weinholdstatus_t	_user_set_debugger_breakpoint(void *address, uint32 type,
28944b5d72bSIngo Weinhold				int32 length, bool watchpoint);
29044b5d72bSIngo Weinholdstatus_t	_user_clear_debugger_breakpoint(void *address, bool watchpoint);
29144b5d72bSIngo Weinhold
292b959d46dSMichael Lotzssize_t		_user_get_stack_trace(size_t addressCount, addr_t* returnAddresses);
293bc797a9eSIngo Weinhold
294bc797a9eSIngo Weinhold#ifdef __cplusplus
295bc797a9eSIngo Weinhold}	// extern "C"
296bc797a9eSIngo Weinhold#endif
297bc797a9eSIngo Weinhold
298bc797a9eSIngo Weinhold
299bc797a9eSIngo Weinhold#endif	// _KERNEL_USER_DEBUGGER_H