xref: /haiku/headers/private/kernel/user_debugger.h (revision 24159a0c7d6d6dcba9f2a0c1a7c08d2c8167f21b)
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		= B_TEAM_DEBUG_SIGNALS
78 									  | B_TEAM_DEBUG_PRE_SYSCALL
79 									  | B_TEAM_DEBUG_POST_SYSCALL,
80 };
81 
82 // thread debugging flags (user-specifiable flags are in <debugger.h>)
83 enum {
84 	B_THREAD_DEBUG_INITIALIZED		= 0x0001,
85 	B_THREAD_DEBUG_DYING			= 0x0002,
86 	B_THREAD_DEBUG_STOP				= 0x0004,
87 	B_THREAD_DEBUG_STOPPED			= 0x0008,
88 	B_THREAD_DEBUG_SINGLE_STEP		= 0x0010,
89 
90 	B_THREAD_DEBUG_NUB_THREAD		= 0x0020,	// marks the nub thread
91 
92 	B_THREAD_DEBUG_KERNEL_FLAG_MASK	= 0xffff,
93 
94 	B_THREAD_DEBUG_DEFAULT_FLAGS	= 0,
95 };
96 
97 // messages sent from the debug nub thread to a debugged thread
98 typedef enum {
99 	B_DEBUGGED_THREAD_MESSAGE_CONTINUE	= 0,
100 	B_DEBUGGED_THREAD_SET_CPU_STATE,
101 	B_DEBUGGED_THREAD_GET_CPU_STATE,
102 	B_DEBUGGED_THREAD_DEBUGGER_CHANGED,
103 } debugged_thread_message;
104 
105 typedef struct {
106 	uint32	handle_event;
107 	bool	single_step;
108 } debugged_thread_continue;
109 
110 typedef struct {
111 	port_id	reply_port;
112 } debugged_thread_get_cpu_state;
113 
114 typedef struct {
115 	debug_cpu_state	cpu_state;
116 } debugged_thread_set_cpu_state;
117 
118 typedef union {
119 	debugged_thread_continue		continue_thread;
120 	debugged_thread_set_cpu_state	set_cpu_state;
121 	debugged_thread_get_cpu_state	get_cpu_state;
122 } debugged_thread_message_data;
123 
124 
125 // internal messages sent to the nub thread
126 typedef enum {
127 	B_DEBUG_MESSAGE_HANDED_OVER		= -1,
128 } debug_nub_kernel_message;
129 
130 
131 #ifdef __cplusplus
132 extern "C" {
133 #endif
134 
135 // service calls
136 
137 void clear_team_debug_info(struct team_debug_info *info, bool initLock);
138 void destroy_team_debug_info(struct team_debug_info *info);
139 
140 void clear_thread_debug_info(struct thread_debug_info *info,
141 		bool dying);
142 void destroy_thread_debug_info(struct thread_debug_info *info);
143 
144 void user_debug_prepare_for_exec();
145 void user_debug_finish_after_exec();
146 
147 void init_user_debug();
148 
149 // debug event callbacks
150 
151 void user_debug_pre_syscall(uint32 syscall, void *args);
152 void user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue,
153 		bigtime_t startTime);
154 bool user_debug_exception_occurred(debug_exception_type exception, int signal);
155 bool user_debug_handle_signal(int signal, struct sigaction *handler,
156 		bool deadly);
157 void user_debug_stop_thread();
158 void user_debug_team_created(team_id teamID);
159 void user_debug_team_deleted(team_id teamID, port_id debuggerPort);
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 
181 #ifdef __cplusplus
182 }	// extern "C"
183 #endif
184 
185 
186 #endif	// _KERNEL_USER_DEBUGGER_H
187