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