1 /* 2 * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. 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 #include <timer.h> 15 16 17 // limits 18 #define B_DEBUG_MIN_PROFILE_INTERVAL 10 /* in us */ 19 #define B_DEBUG_STACK_TRACE_DEPTH 128 20 #define B_DEBUG_PROFILE_BUFFER_FLUSH_THRESHOLD 70 /* in % */ 21 22 23 struct function_profile_info; 24 struct thread; 25 26 // Team related debugging data. 27 // 28 // Locking policy: 29 // 1) When accessing the structure it must be made sure, that the structure, 30 // (i.e. the struct team it lives in) isn't deleted. Thus one either needs to 31 // acquire the global team lock, or one accesses the structure from a thread 32 // of that team. 33 // 2) Access to the `flags' field is atomically. Reading via atomic_get() 34 // requires no further locks (in addition to 1) that is). Writing requires 35 // `lock' being held and must be done atomically, too 36 // (atomic_{set,and,or}()). Reading with `lock' being held doesn't need to 37 // be done atomically. 38 // 3) Access to all other fields (read or write) requires `lock' being held. 39 // 40 struct team_debug_info { 41 spinlock lock; 42 // Guards the remaining fields. Should always be the innermost lock 43 // to be acquired/released. 44 45 int32 flags; 46 // Set atomically. So reading atomically is OK, even when the team 47 // lock is not held (at least if it is certain, that the team struct 48 // won't go). 49 50 team_id debugger_team; 51 port_id debugger_port; 52 thread_id nub_thread; 53 port_id nub_port; 54 // the port the nub thread is waiting on for commands from the debugger 55 sem_id debugger_write_lock; 56 // synchronizes writes to the debugger port with the setting (but not 57 // clearing) of the B_TEAM_DEBUG_DEBUGGER_HANDOVER flag 58 thread_id causing_thread; 59 // thread that caused the debugger to be attached; -1 for manual 60 // debugger attachment (or no debugger installed) 61 vint32 image_event; 62 // counter incremented whenever an image is created/deleted 63 64 struct arch_team_debug_info arch_info; 65 }; 66 67 struct thread_debug_info { 68 int32 flags; 69 // Set atomically. So reading atomically is OK, even when the thread 70 // lock is not held (at least if it is certain, that the thread struct 71 // won't go). 72 port_id debug_port; 73 // the port the thread is waiting on for commands from the nub thread 74 75 sigset_t ignore_signals; 76 // the signals the debugger is not interested in 77 sigset_t ignore_signals_once; 78 // the signals the debugger wishes not to be notified of, when they 79 // occur the next time 80 81 // profiling related part; if samples != NULL, the thread is profiled 82 struct { 83 bigtime_t interval; 84 // sampling interval 85 area_id sample_area; 86 // cloned sample buffer area 87 addr_t* samples; 88 // sample buffer 89 int32 max_samples; 90 // maximum number of samples the buffer can hold 91 int32 flush_threshold; 92 // number of sample when the buffer is flushed (if possible) 93 int32 sample_count; 94 // number of samples the buffer currently holds 95 int32 stack_depth; 96 // number of return addresses to record per timer interval 97 int32 dropped_ticks; 98 // number of ticks that had to be dropped when the sample buffer was 99 // full and couldn't be flushed 100 int32 image_event; 101 // number of the image event when the first sample was written into 102 // the buffer 103 int32 last_image_event; 104 // number of the image event when the last sample was written into 105 // the buffer 106 bool variable_stack_depth; 107 // record a variable number of samples per hit 108 bool buffer_full; 109 // indicates that the sample buffer is full 110 union { 111 bigtime_t interval_left; 112 // when unscheduled: the time left of the current sampling 113 // interval 114 bigtime_t timer_end; 115 // when running: the absolute time the timer is supposed to go 116 // off 117 }; 118 timer* installed_timer; 119 // when running and being profiled: the CPU's profiling timer 120 } profile; 121 122 struct arch_thread_debug_info arch_info; 123 }; 124 125 #define GRAB_TEAM_DEBUG_INFO_LOCK(info) acquire_spinlock(&(info).lock) 126 #define RELEASE_TEAM_DEBUG_INFO_LOCK(info) release_spinlock(&(info).lock) 127 128 // team debugging flags (user-specifiable flags are in <debugger.h>) 129 enum { 130 B_TEAM_DEBUG_DEBUGGER_INSTALLED = 0x0001, 131 B_TEAM_DEBUG_DEBUGGER_HANDOVER = 0x0002, // marked for hand-over 132 B_TEAM_DEBUG_DEBUGGER_HANDING_OVER = 0x0004, // handing over 133 B_TEAM_DEBUG_DEBUGGER_DISABLED = 0x0008, 134 135 B_TEAM_DEBUG_KERNEL_FLAG_MASK = 0xffff, 136 137 B_TEAM_DEBUG_DEFAULT_FLAGS = 0, 138 }; 139 140 // thread debugging flags (user-specifiable flags are in <debugger.h>) 141 enum { 142 B_THREAD_DEBUG_INITIALIZED = 0x0001, 143 B_THREAD_DEBUG_DYING = 0x0002, 144 B_THREAD_DEBUG_STOP = 0x0004, 145 B_THREAD_DEBUG_STOPPED = 0x0008, 146 B_THREAD_DEBUG_SINGLE_STEP = 0x0010, 147 148 B_THREAD_DEBUG_NUB_THREAD = 0x0020, // marks the nub thread 149 150 B_THREAD_DEBUG_KERNEL_FLAG_MASK = 0xffff, 151 152 B_THREAD_DEBUG_DEFAULT_FLAGS = 0, 153 }; 154 155 // messages sent from the debug nub thread to a debugged thread 156 typedef enum { 157 B_DEBUGGED_THREAD_MESSAGE_CONTINUE = 0, 158 B_DEBUGGED_THREAD_SET_CPU_STATE, 159 B_DEBUGGED_THREAD_GET_CPU_STATE, 160 B_DEBUGGED_THREAD_DEBUGGER_CHANGED, 161 } debugged_thread_message; 162 163 typedef struct { 164 uint32 handle_event; 165 bool single_step; 166 } debugged_thread_continue; 167 168 typedef struct { 169 port_id reply_port; 170 } debugged_thread_get_cpu_state; 171 172 typedef struct { 173 debug_cpu_state cpu_state; 174 } debugged_thread_set_cpu_state; 175 176 typedef union { 177 debugged_thread_continue continue_thread; 178 debugged_thread_set_cpu_state set_cpu_state; 179 debugged_thread_get_cpu_state get_cpu_state; 180 } debugged_thread_message_data; 181 182 183 // internal messages sent to the nub thread 184 typedef enum { 185 B_DEBUG_MESSAGE_HANDED_OVER = -1, 186 } debug_nub_kernel_message; 187 188 189 #ifdef __cplusplus 190 extern "C" { 191 #endif 192 193 // service calls 194 195 void clear_team_debug_info(struct team_debug_info *info, bool initLock); 196 void destroy_team_debug_info(struct team_debug_info *info); 197 198 void init_thread_debug_info(struct thread_debug_info *info); 199 void clear_thread_debug_info(struct thread_debug_info *info, bool dying); 200 void destroy_thread_debug_info(struct thread_debug_info *info); 201 202 void user_debug_prepare_for_exec(); 203 void user_debug_finish_after_exec(); 204 205 void init_user_debug(); 206 207 208 // debug event callbacks 209 210 void user_debug_pre_syscall(uint32 syscall, void *args); 211 void user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue, 212 bigtime_t startTime); 213 bool user_debug_exception_occurred(debug_exception_type exception, int signal); 214 bool user_debug_handle_signal(int signal, struct sigaction *handler, 215 bool deadly); 216 void user_debug_stop_thread(); 217 void user_debug_team_created(team_id teamID); 218 void user_debug_team_deleted(team_id teamID, port_id debuggerPort); 219 void user_debug_team_exec(); 220 void user_debug_update_new_thread_flags(thread_id threadID); 221 void user_debug_thread_created(thread_id threadID); 222 void user_debug_thread_deleted(team_id teamID, thread_id threadID); 223 void user_debug_thread_exiting(struct thread* thread); 224 void user_debug_image_created(const image_info *imageInfo); 225 void user_debug_image_deleted(const image_info *imageInfo); 226 void user_debug_breakpoint_hit(bool software); 227 void user_debug_watchpoint_hit(); 228 void user_debug_single_stepped(); 229 230 void user_debug_thread_unscheduled(struct thread* thread); 231 void user_debug_thread_scheduled(struct thread* thread); 232 233 234 // syscalls 235 236 void _user_debugger(const char *message); 237 int _user_disable_debugger(int state); 238 239 status_t _user_install_default_debugger(port_id debuggerPort); 240 port_id _user_install_team_debugger(team_id team, port_id debuggerPort); 241 status_t _user_remove_team_debugger(team_id team); 242 status_t _user_debug_thread(thread_id thread); 243 void _user_wait_for_debugger(void); 244 245 status_t _user_set_debugger_breakpoint(void *address, uint32 type, 246 int32 length, bool watchpoint); 247 status_t _user_clear_debugger_breakpoint(void *address, bool watchpoint); 248 249 250 #ifdef __cplusplus 251 } // extern "C" 252 #endif 253 254 255 #endif // _KERNEL_USER_DEBUGGER_H 256