events.c revision 69a03e6f8c15fb0272089e387a658acad887fb9c
1#include "config.h" 2 3#define _GNU_SOURCE 1 4#include <stdlib.h> 5#include <sys/types.h> 6#include <sys/wait.h> 7#include <errno.h> 8#include <signal.h> 9#include <string.h> 10#include <sys/ptrace.h> 11#include <assert.h> 12 13#include "common.h" 14 15static Event event; 16 17/* A queue of events that we missed while enabling the 18 * breakpoint in one of tasks. */ 19static Event * delayed_events = NULL; 20static Event * end_delayed_events = NULL; 21 22static enum pcb_status 23first (Process * proc, void * data) 24{ 25 return pcb_stop; 26} 27 28void 29enque_event(Event * event) 30{ 31 debug(DEBUG_FUNCTION, "%d: queuing event %d for later", 32 event->proc->pid, event->type); 33 Event * ne = malloc(sizeof(*ne)); 34 if (ne == NULL) { 35 perror("event will be missed: malloc"); 36 return; 37 } 38 39 *ne = *event; 40 ne->next = NULL; 41 if (end_delayed_events == NULL) { 42 assert(delayed_events == NULL); 43 end_delayed_events = delayed_events = ne; 44 } 45 else { 46 assert(delayed_events != NULL); 47 end_delayed_events = end_delayed_events->next = ne; 48 } 49} 50 51Event * 52each_qd_event(enum ecb_status (*pred)(Event *, void *), void * data) 53{ 54 Event * prev = delayed_events; 55 Event * event; 56 for (event = prev; event != NULL; ) { 57 switch ((*pred)(event, data)) { 58 case ecb_cont: 59 prev = event; 60 event = event->next; 61 continue; 62 63 case ecb_deque: 64 debug(DEBUG_FUNCTION, "dequeuing event %d for %d", 65 event->type, 66 event->proc != NULL ? event->proc->pid : -1); 67 /* 68 printf("dequeuing event %d for %d\n", event->type, 69 event->proc != NULL ? event->proc->pid : -1) ; 70 */ 71 if (end_delayed_events == event) 72 end_delayed_events = prev; 73 if (delayed_events == event) 74 delayed_events = event->next; 75 else 76 prev->next = event->next; 77 if (delayed_events == NULL) 78 end_delayed_events = NULL; 79 /* fall-through */ 80 81 case ecb_yield: 82 return event; 83 } 84 } 85 86 return NULL; 87} 88 89static enum ecb_status 90event_process_not_reenabling(Event * event, void * data) 91{ 92 return ecb_deque; 93} 94 95static Event * 96next_qd_event(void) 97{ 98 return each_qd_event(&event_process_not_reenabling, NULL); 99} 100 101Event * 102next_event(void) 103{ 104 pid_t pid; 105 int status; 106 int tmp; 107 int stop_signal; 108 109 debug(DEBUG_FUNCTION, "next_event()"); 110 Event * ev; 111 if ((ev = next_qd_event()) != NULL) { 112 event = *ev; 113 free(ev); 114 return &event; 115 } 116 117 if (!each_process(NULL, &first, NULL)) { 118 debug(DEBUG_EVENT, "event: No more traced programs: exiting"); 119 exit(0); 120 } 121 pid = waitpid(-1, &status, __WALL); 122 if (pid == -1) { 123 if (errno == ECHILD) { 124 debug(DEBUG_EVENT, "event: No more traced programs: exiting"); 125 exit(0); 126 } else if (errno == EINTR) { 127 debug(DEBUG_EVENT, "event: none (wait received EINTR?)"); 128 event.type = EVENT_NONE; 129 return &event; 130 } 131 perror("wait"); 132 exit(1); 133 } 134 event.proc = pid2proc(pid); 135 if (!event.proc || event.proc->state == STATE_BEING_CREATED) { 136 event.type = EVENT_NEW; 137 event.e_un.newpid = pid; 138 debug(DEBUG_EVENT, "event: NEW: pid=%d", pid); 139 return &event; 140 } 141 get_arch_dep(event.proc); 142 debug(3, "event from pid %u", pid); 143 if (event.proc->breakpoints_enabled == -1) 144 trace_set_options(event.proc, event.proc->pid); 145 Process *leader = event.proc->leader; 146 if (leader == event.proc) { 147 if (event.proc->breakpoints_enabled == -1) { 148 event.type = EVENT_NONE; 149 enable_all_breakpoints(event.proc); 150 continue_process(event.proc->pid); 151 debug(DEBUG_EVENT, 152 "event: NONE: pid=%d (enabling breakpoints)", 153 pid); 154 return &event; 155 } else if (!event.proc->libdl_hooked) { 156 /* debug struct may not have been written yet.. */ 157 if (linkmap_init(event.proc, &main_lte) == 0) { 158 event.proc->libdl_hooked = 1; 159 } 160 } 161 } 162 163 event.proc->instruction_pointer = (void *)(uintptr_t)-1; 164 165 event.proc->instruction_pointer = get_instruction_pointer(event.proc); 166 if (event.proc->instruction_pointer == (void *)(uintptr_t)-1) { 167 if (errno != 0) 168 perror("get_instruction_pointer"); 169 } 170 171 switch (syscall_p(event.proc, status, &tmp)) { 172 case 1: 173 event.type = EVENT_SYSCALL; 174 event.e_un.sysnum = tmp; 175 debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp); 176 return &event; 177 case 2: 178 event.type = EVENT_SYSRET; 179 event.e_un.sysnum = tmp; 180 debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp); 181 return &event; 182 case 3: 183 event.type = EVENT_ARCH_SYSCALL; 184 event.e_un.sysnum = tmp; 185 debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp); 186 return &event; 187 case 4: 188 event.type = EVENT_ARCH_SYSRET; 189 event.e_un.sysnum = tmp; 190 debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp); 191 return &event; 192 case -1: 193 event.type = EVENT_NONE; 194 continue_process(event.proc->pid); 195 debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid); 196 return &event; 197 } 198 if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) { 199 unsigned long data; 200 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data); 201 event.type = EVENT_CLONE; 202 event.e_un.newpid = data; 203 debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data); 204 return &event; 205 } 206 if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) { 207 event.type = EVENT_EXEC; 208 debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid); 209 return &event; 210 } 211 if (WIFEXITED(status)) { 212 event.type = EVENT_EXIT; 213 event.e_un.ret_val = WEXITSTATUS(status); 214 debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val); 215 return &event; 216 } 217 if (WIFSIGNALED(status)) { 218 event.type = EVENT_EXIT_SIGNAL; 219 event.e_un.signum = WTERMSIG(status); 220 debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum); 221 return &event; 222 } 223 if (!WIFSTOPPED(status)) { 224 /* should never happen */ 225 event.type = EVENT_NONE; 226 debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid); 227 return &event; 228 } 229 230 stop_signal = WSTOPSIG(status); 231 232 /* On some targets, breakpoints are signalled not using 233 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. SIGEMT 234 is not defined on Linux, but check for the others. 235 236 N.B. see comments in GDB's infrun.c for details. I've 237 actually seen this on an Itanium machine on RHEL 5, I don't 238 remember the exact kernel version anymore. ia64-sigill.s 239 in the test suite tests this. Petr Machata 2011-06-08. */ 240 void * break_address 241 = event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; 242 if ((stop_signal == SIGSEGV || stop_signal == SIGILL) 243 && leader != NULL 244 && address2bpstruct(leader, break_address)) 245 stop_signal = SIGTRAP; 246 247 if (stop_signal != (SIGTRAP | event.proc->tracesysgood) 248 && stop_signal != SIGTRAP) { 249 event.type = EVENT_SIGNAL; 250 event.e_un.signum = stop_signal; 251 debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal); 252 return &event; 253 } 254 255 /* last case [by exhaustion] */ 256 event.type = EVENT_BREAKPOINT; 257 258 event.e_un.brk_addr = break_address; 259 debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr); 260 261 return &event; 262} 263