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