xref: /haiku/headers/private/kernel/user_debugger.h (revision 8195a5a835117ab2da405e0d477153570b75d921)
1 /*
2  * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3  * Distributed under the terms of the MIT License.
4  *
5  * Userland debugger support.
6  */
7 #ifndef _KERNEL_USER_DEBUGGER_H
8 #define _KERNEL_USER_DEBUGGER_H
9 
10 #include <debugger.h>
11 
12 #include <arch/user_debugger.h>
13 
14 // Team related debugging data.
15 //
16 // Locking policy:
17 // 1) When accessing the structure it must be made sure, that the structure,
18 //    (i.e. the struct team it lives in) isn't deleted. Thus one either needs to
19 //    acquire the global team lock, or one accesses the structure from a thread
20 //    of that team.
21 // 2) Access to the `flags' field is atomically. Reading via atomic_get()
22 //    requires no further locks (in addition to 1) that is). Writing requires
23 //    `lock' being held and must be done atomically, too
24 //    (atomic_{set,and,or}()). Reading with `lock' being held doesn't need to
25 //    be done atomically.
26 // 3) Access to all other fields (read or write) requires `lock' being held.
27 //
28 struct team_debug_info {
29 	spinlock	lock;
30 		// Guards the remaining fields. Should always be the innermost lock
31 		// to be acquired/released.
32 
33 	int32		flags;
34 		// Set atomically. So reading atomically is OK, even when the team
35 		// lock is not held (at least if it is certain, that the team struct
36 		// won't go).
37 
38 	team_id		debugger_team;
39 	port_id		debugger_port;
40 	thread_id	nub_thread;
41 	port_id		nub_port;
42 		// the port the nub thread is waiting on for commands from the debugger
43 	sem_id		debugger_write_lock;
44 		// synchronizes writes to the debugger port with the setting (but not
45 		// clearing) of the B_TEAM_DEBUG_DEBUGGER_HANDOVER flag
46 
47 	struct arch_team_debug_info	arch_info;
48 };
49 
50 struct thread_debug_info {
51 	int32		flags;
52 		// Set atomically. So reading atomically is OK, even when the thread
53 		// lock is not held (at least if it is certain, that the thread struct
54 		// won't go).
55 	port_id		debug_port;
56 		// the port the thread is waiting on for commands from the nub thread
57 
58 	sigset_t	ignore_signals;
59 		// the signals the debugger is not interested in
60 	sigset_t	ignore_signals_once;
61 		// the signals the debugger wishes not to be notified of, when they
62 		// occur the next time
63 
64 	struct arch_thread_debug_info	arch_info;
65 };
66 
67 #define GRAB_TEAM_DEBUG_INFO_LOCK(info)		acquire_spinlock(&(info).lock)
68 #define RELEASE_TEAM_DEBUG_INFO_LOCK(info)	release_spinlock(&(info).lock)
69 
70 // team debugging flags (user-specifiable flags are in <debugger.h>)
71 enum {
72 	B_TEAM_DEBUG_DEBUGGER_INSTALLED	= 0x0001,
73 	B_TEAM_DEBUG_DEBUGGER_HANDOVER	= 0x0002,
74 
75 	B_TEAM_DEBUG_KERNEL_FLAG_MASK	= 0xffff,
76 
77 	B_TEAM_DEBUG_DEFAULT_FLAGS		= 0,
78 };
79 
80 // thread debugging flags (user-specifiable flags are in <debugger.h>)
81 enum {
82 	B_THREAD_DEBUG_INITIALIZED		= 0x0001,
83 	B_THREAD_DEBUG_DYING			= 0x0002,
84 	B_THREAD_DEBUG_STOP				= 0x0004,
85 	B_THREAD_DEBUG_STOPPED			= 0x0008,
86 	B_THREAD_DEBUG_SINGLE_STEP		= 0x0010,
87 
88 	B_THREAD_DEBUG_NUB_THREAD		= 0x0020,	// marks the nub thread
89 
90 	B_THREAD_DEBUG_KERNEL_FLAG_MASK	= 0xffff,
91 
92 	B_THREAD_DEBUG_DEFAULT_FLAGS	= 0,
93 };
94 
95 // messages sent from the debug nub thread to a debugged thread
96 typedef enum {
97 	B_DEBUGGED_THREAD_MESSAGE_CONTINUE	= 0,
98 	B_DEBUGGED_THREAD_SET_CPU_STATE,
99 	B_DEBUGGED_THREAD_GET_CPU_STATE,
100 	B_DEBUGGED_THREAD_DEBUGGER_CHANGED,
101 } debugged_thread_message;
102 
103 typedef struct {
104 	uint32	handle_event;
105 	bool	single_step;
106 } debugged_thread_continue;
107 
108 typedef struct {
109 	port_id	reply_port;
110 } debugged_thread_get_cpu_state;
111 
112 typedef struct {
113 	debug_cpu_state	cpu_state;
114 } debugged_thread_set_cpu_state;
115 
116 typedef union {
117 	debugged_thread_continue		continue_thread;
118 	debugged_thread_set_cpu_state	set_cpu_state;
119 	debugged_thread_get_cpu_state	get_cpu_state;
120 } debugged_thread_message_data;
121 
122 
123 // internal messages sent to the nub thread
124 typedef enum {
125 	B_DEBUG_MESSAGE_HANDED_OVER		= -1,
126 } debug_nub_kernel_message;
127 
128 
129 #ifdef __cplusplus
130 extern "C" {
131 #endif
132 
133 // service calls
134 
135 void clear_team_debug_info(struct team_debug_info *info, bool initLock);
136 void destroy_team_debug_info(struct team_debug_info *info);
137 
138 void clear_thread_debug_info(struct thread_debug_info *info,
139 		bool dying);
140 void destroy_thread_debug_info(struct thread_debug_info *info);
141 
142 void user_debug_prepare_for_exec();
143 void user_debug_finish_after_exec();
144 
145 void init_user_debug();
146 
147 
148 // debug event callbacks
149 
150 void user_debug_pre_syscall(uint32 syscall, void *args);
151 void user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
152 		bigtime_t startTime);
153 bool user_debug_exception_occurred(debug_exception_type exception, int signal);
154 bool user_debug_handle_signal(int signal, struct sigaction *handler,
155 		bool deadly);
156 void user_debug_stop_thread();
157 void user_debug_team_created(team_id teamID);
158 void user_debug_team_deleted(team_id teamID, port_id debuggerPort);
159 void user_debug_update_new_thread_flags(thread_id threadID);
160 void user_debug_thread_created(thread_id threadID);
161 void user_debug_thread_deleted(team_id teamID, thread_id threadID);
162 void user_debug_image_created(const image_info *imageInfo);
163 void user_debug_image_deleted(const image_info *imageInfo);
164 void user_debug_breakpoint_hit(bool software);
165 void user_debug_watchpoint_hit();
166 void user_debug_single_stepped();
167 
168 
169 // syscalls
170 
171 void		_user_debugger(const char *message);
172 int			_user_disable_debugger(int state);
173 
174 status_t	_user_install_default_debugger(port_id debuggerPort);
175 port_id		_user_install_team_debugger(team_id team, port_id debuggerPort);
176 status_t	_user_remove_team_debugger(team_id team);
177 status_t	_user_debug_thread(thread_id thread);
178 void		_user_wait_for_debugger(void);
179 
180 status_t	_user_set_debugger_breakpoint(void *address, uint32 type,
181 				int32 length, bool watchpoint);
182 status_t	_user_clear_debugger_breakpoint(void *address, bool watchpoint);
183 
184 
185 #ifdef __cplusplus
186 }	// extern "C"
187 #endif
188 
189 
190 #endif	// _KERNEL_USER_DEBUGGER_H
191