events.c revision f670eea50e959eeb9da53d70cad8d43c19494ef0
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 12#include "common.h" 13 14static Event event; 15 16Event * 17next_event(void) { 18 pid_t pid; 19 int status; 20 int tmp; 21 int stop_signal; 22 23 debug(DEBUG_FUNCTION, "next_event()"); 24 if (!list_of_processes) { 25 debug(DEBUG_EVENT, "event: No more traced programs: exiting"); 26 exit(0); 27 } 28 pid = waitpid(-1, &status, __WALL); 29 if (pid == -1) { 30 if (errno == ECHILD) { 31 debug(DEBUG_EVENT, "event: No more traced programs: exiting"); 32 exit(0); 33 } else if (errno == EINTR) { 34 debug(DEBUG_EVENT, "event: none (wait received EINTR?)"); 35 event.type = EVENT_NONE; 36 return &event; 37 } 38 perror("wait"); 39 exit(1); 40 } 41 event.proc = pid2proc(pid); 42 if (!event.proc || event.proc->state == STATE_BEING_CREATED) { 43 event.type = EVENT_NEW; 44 event.e_un.newpid = pid; 45 debug(DEBUG_EVENT, "event: NEW: pid=%d", pid); 46 return &event; 47 } 48 get_arch_dep(event.proc); 49 event.proc->instruction_pointer = NULL; 50 debug(3, "event from pid %u", pid); 51 if (event.proc->breakpoints_enabled == -1) { 52 enable_all_breakpoints(event.proc); 53 event.type = EVENT_NONE; 54 trace_set_options(event.proc, event.proc->pid); 55 continue_process(event.proc->pid); 56 debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid); 57 return &event; 58 } 59 if (opt_i) { 60 event.proc->instruction_pointer = 61 get_instruction_pointer(event.proc); 62 } 63 switch (syscall_p(event.proc, status, &tmp)) { 64 case 1: 65 event.type = EVENT_SYSCALL; 66 event.e_un.sysnum = tmp; 67 debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp); 68 return &event; 69 case 2: 70 event.type = EVENT_SYSRET; 71 event.e_un.sysnum = tmp; 72 debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp); 73 return &event; 74 case 3: 75 event.type = EVENT_ARCH_SYSCALL; 76 event.e_un.sysnum = tmp; 77 debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp); 78 return &event; 79 case 4: 80 event.type = EVENT_ARCH_SYSRET; 81 event.e_un.sysnum = tmp; 82 debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp); 83 return &event; 84 case -1: 85 event.type = EVENT_NONE; 86 continue_process(event.proc->pid); 87 debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid); 88 return &event; 89 } 90 if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) { 91 unsigned long data; 92 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data); 93 event.type = EVENT_CLONE; 94 event.e_un.newpid = data; 95 debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data); 96 return &event; 97 } 98 if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) { 99 event.type = EVENT_EXEC; 100 debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid); 101 return &event; 102 } 103 if (WIFEXITED(status)) { 104 event.type = EVENT_EXIT; 105 event.e_un.ret_val = WEXITSTATUS(status); 106 debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val); 107 return &event; 108 } 109 if (WIFSIGNALED(status)) { 110 event.type = EVENT_EXIT_SIGNAL; 111 event.e_un.signum = WTERMSIG(status); 112 debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum); 113 return &event; 114 } 115 if (!WIFSTOPPED(status)) { 116 /* should never happen */ 117 event.type = EVENT_NONE; 118 debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid); 119 return &event; 120 } 121 122 stop_signal = WSTOPSIG(status); 123 124 /* On some targets, breakpoints are signalled not using 125 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check 126 for these. (TODO: is this true?) */ 127 if (stop_signal == SIGSEGV 128 || stop_signal == SIGILL 129#ifdef SIGEMT 130 || stop_signal == SIGEMT 131#endif 132 ) { 133 if (!event.proc->instruction_pointer) { 134 event.proc->instruction_pointer = 135 get_instruction_pointer(event.proc); 136 } 137 138 if (address2bpstruct(event.proc, event.proc->instruction_pointer)) 139 stop_signal = SIGTRAP; 140 } 141 142 if (stop_signal != (SIGTRAP | event.proc->tracesysgood) 143 && stop_signal != SIGTRAP) { 144 event.type = EVENT_SIGNAL; 145 event.e_un.signum = stop_signal; 146 debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal); 147 return &event; 148 } 149 150 /* last case [by exhaustion] */ 151 event.type = EVENT_BREAKPOINT; 152 153 if (!event.proc->instruction_pointer) { 154 event.proc->instruction_pointer = 155 get_instruction_pointer(event.proc); 156 } 157 event.e_un.brk_addr = 158 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; 159 debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr); 160 return &event; 161} 162