events.c revision 9a5420c82a2fd81681572a2e3859ea1671c3bded
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 16static enum pcb_status 17first (Process * proc, void * data) 18{ 19 return pcb_stop; 20} 21 22Event * 23next_event(void) 24{ 25 pid_t pid; 26 int status; 27 int tmp; 28 int stop_signal; 29 30 debug(DEBUG_FUNCTION, "next_event()"); 31 if (!each_process(NULL, &first, NULL)) { 32 debug(DEBUG_EVENT, "event: No more traced programs: exiting"); 33 exit(0); 34 } 35 pid = waitpid(-1, &status, __WALL); 36 if (pid == -1) { 37 if (errno == ECHILD) { 38 debug(DEBUG_EVENT, "event: No more traced programs: exiting"); 39 exit(0); 40 } else if (errno == EINTR) { 41 debug(DEBUG_EVENT, "event: none (wait received EINTR?)"); 42 event.type = EVENT_NONE; 43 return &event; 44 } 45 perror("wait"); 46 exit(1); 47 } 48 event.proc = pid2proc(pid); 49 if (!event.proc || event.proc->state == STATE_BEING_CREATED) { 50 event.type = EVENT_NEW; 51 event.e_un.newpid = pid; 52 debug(DEBUG_EVENT, "event: NEW: pid=%d", pid); 53 return &event; 54 } 55 get_arch_dep(event.proc); 56 debug(3, "event from pid %u", pid); 57 if (event.proc->breakpoints_enabled == -1) 58 trace_set_options(event.proc, event.proc->pid); 59 Process *leader = event.proc->leader; 60 if (leader == event.proc) { 61 if (event.proc->breakpoints_enabled == -1) { 62 event.type = EVENT_NONE; 63 enable_all_breakpoints(event.proc); 64 continue_process(event.proc->pid); 65 debug(DEBUG_EVENT, 66 "event: NONE: pid=%d (enabling breakpoints)", 67 pid); 68 return &event; 69 } else if (!event.proc->libdl_hooked) { 70 /* debug struct may not have been written yet.. */ 71 if (linkmap_init(event.proc, &main_lte) == 0) { 72 event.proc->libdl_hooked = 1; 73 } 74 } 75 } 76 77 event.proc->instruction_pointer = (void *)(uintptr_t)-1; 78 79 event.proc->instruction_pointer = get_instruction_pointer(event.proc); 80 if (event.proc->instruction_pointer == (void *)(uintptr_t)-1) { 81 if (errno != 0) 82 perror("get_instruction_pointer"); 83 } 84 85 switch (syscall_p(event.proc, status, &tmp)) { 86 case 1: 87 event.type = EVENT_SYSCALL; 88 event.e_un.sysnum = tmp; 89 debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp); 90 return &event; 91 case 2: 92 event.type = EVENT_SYSRET; 93 event.e_un.sysnum = tmp; 94 debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp); 95 return &event; 96 case 3: 97 event.type = EVENT_ARCH_SYSCALL; 98 event.e_un.sysnum = tmp; 99 debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp); 100 return &event; 101 case 4: 102 event.type = EVENT_ARCH_SYSRET; 103 event.e_un.sysnum = tmp; 104 debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp); 105 return &event; 106 case -1: 107 event.type = EVENT_NONE; 108 continue_process(event.proc->pid); 109 debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid); 110 return &event; 111 } 112 if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) { 113 unsigned long data; 114 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data); 115 event.type = EVENT_CLONE; 116 event.e_un.newpid = data; 117 debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data); 118 return &event; 119 } 120 if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) { 121 event.type = EVENT_EXEC; 122 debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid); 123 return &event; 124 } 125 if (WIFEXITED(status)) { 126 event.type = EVENT_EXIT; 127 event.e_un.ret_val = WEXITSTATUS(status); 128 debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val); 129 return &event; 130 } 131 if (WIFSIGNALED(status)) { 132 event.type = EVENT_EXIT_SIGNAL; 133 event.e_un.signum = WTERMSIG(status); 134 debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum); 135 return &event; 136 } 137 if (!WIFSTOPPED(status)) { 138 /* should never happen */ 139 event.type = EVENT_NONE; 140 debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid); 141 return &event; 142 } 143 144 stop_signal = WSTOPSIG(status); 145 146 /* On some targets, breakpoints are signalled not using 147 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. SIGEMT 148 is not defined on Linux, but check for the others. 149 150 N.B. see comments in GDB's infrun.c for details. I've 151 actually seen this on an Itanium machine on RHEL 5, I don't 152 remember the exact kernel version anymore. ia64-sigill.s 153 in the test suite tests this. Petr Machata 2011-06-08. */ 154 void * break_address 155 = event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; 156 if ((stop_signal == SIGSEGV || stop_signal == SIGILL) 157 && leader != NULL 158 && address2bpstruct(leader, break_address)) 159 stop_signal = SIGTRAP; 160 161 if (stop_signal != (SIGTRAP | event.proc->tracesysgood) 162 && stop_signal != SIGTRAP) { 163 event.type = EVENT_SIGNAL; 164 event.e_un.signum = stop_signal; 165 debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal); 166 return &event; 167 } 168 169 /* last case [by exhaustion] */ 170 event.type = EVENT_BREAKPOINT; 171 172 event.e_un.brk_addr = break_address; 173 debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr); 174 175 return &event; 176} 177