blob: 4f5671bad14a311528981f4de6d21121e06c8af2 [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5e01f651998-03-08 22:31:44 +01005#define _GNU_SOURCE 1
Juan Cespedes1cd999a2001-07-03 00:46:04 +02006#include <stdlib.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01007#include <sys/types.h>
8#include <sys/wait.h>
9#include <errno.h>
10#include <signal.h>
11#include <string.h>
Juan Cespedes1e583132009-04-07 18:17:11 +020012#include <sys/ptrace.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010013
Juan Cespedesf7281232009-06-25 16:11:21 +020014#include "common.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010015
Juan Cespedes393f1d02009-05-07 11:13:54 +020016static Event event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010017
Juan Cespedes393f1d02009-05-07 11:13:54 +020018Event *
Juan Cespedese2023f72009-04-07 12:12:08 +020019next_event(void) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010020 pid_t pid;
21 int status;
22 int tmp;
Petr Machataef46b3e2007-05-09 19:21:42 +020023 int stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +010024
Juan Cespedescd8976d2009-05-14 13:47:58 +020025 debug(DEBUG_FUNCTION, "next_event()");
Juan Cespedes28f60191998-04-12 00:04:39 +020026 if (!list_of_processes) {
Juan Cespedescd8976d2009-05-14 13:47:58 +020027 debug(DEBUG_EVENT, "event: No more traced programs: exiting");
Juan Cespedes28f60191998-04-12 00:04:39 +020028 exit(0);
29 }
Juan Cespedes6be80282009-05-28 19:06:00 +020030 pid = waitpid(-1, &status, __WALL);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010031 if (pid == -1) {
32 if (errno == ECHILD) {
Juan Cespedescd8976d2009-05-14 13:47:58 +020033 debug(DEBUG_EVENT, "event: No more traced programs: exiting");
Juan Cespedes5e01f651998-03-08 22:31:44 +010034 exit(0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010035 } else if (errno == EINTR) {
Juan Cespedescd8976d2009-05-14 13:47:58 +020036 debug(DEBUG_EVENT, "event: none (wait received EINTR?)");
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020037 event.type = EVENT_NONE;
Juan Cespedes28f60191998-04-12 00:04:39 +020038 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010039 }
40 perror("wait");
41 exit(1);
42 }
43 event.proc = pid2proc(pid);
Juan Cespedes2721e6a2009-05-21 15:15:40 +020044 if (!event.proc || event.proc->state == STATE_BEING_CREATED) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020045 event.type = EVENT_NEW;
Juan Cespedes2721e6a2009-05-21 15:15:40 +020046 event.e_un.newpid = pid;
Juan Cespedescd8976d2009-05-14 13:47:58 +020047 debug(DEBUG_EVENT, "event: NEW: pid=%d", pid);
Juan Cespedesa8909f72009-04-28 20:02:41 +020048 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010049 }
Juan Cespedes5c3fe062004-06-14 18:08:37 +020050 get_arch_dep(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +010051 event.proc->instruction_pointer = NULL;
Juan Cespedes1e583132009-04-07 18:17:11 +020052 debug(3, "event from pid %u", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010053 if (event.proc->breakpoints_enabled == -1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010054 enable_all_breakpoints(event.proc);
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020055 event.type = EVENT_NONE;
Ian Wienand9a2ad352006-02-20 22:44:45 +010056 trace_set_options(event.proc, event.proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010057 continue_process(event.proc->pid);
Juan Cespedescd8976d2009-05-14 13:47:58 +020058 debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010059 return &event;
60 }
Juan Cespedes35d70631998-03-15 14:05:40 +010061 if (opt_i) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010062 event.proc->instruction_pointer =
Juan Cespedes61da3372009-07-03 11:55:44 +020063 get_instruction_pointer(event.proc);
Juan Cespedesf0fdae91998-03-11 00:03:00 +010064 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010065 switch (syscall_p(event.proc, status, &tmp)) {
Juan Cespedes63184be2008-12-10 13:30:12 +010066 case 1:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020067 event.type = EVENT_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010068 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020069 debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010070 return &event;
71 case 2:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020072 event.type = EVENT_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010073 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020074 debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010075 return &event;
76 case 3:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020077 event.type = EVENT_ARCH_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010078 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020079 debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010080 return &event;
81 case 4:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020082 event.type = EVENT_ARCH_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010083 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020084 debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010085 return &event;
86 case -1:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020087 event.type = EVENT_NONE;
Juan Cespedes63184be2008-12-10 13:30:12 +010088 continue_process(event.proc->pid);
Juan Cespedescd8976d2009-05-14 13:47:58 +020089 debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
Juan Cespedes63184be2008-12-10 13:30:12 +010090 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010091 }
Juan Cespedes1e583132009-04-07 18:17:11 +020092 if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
93 unsigned long data;
94 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020095 event.type = EVENT_CLONE;
Juan Cespedes1e583132009-04-07 18:17:11 +020096 event.e_un.newpid = data;
Juan Cespedescd8976d2009-05-14 13:47:58 +020097 debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data);
Juan Cespedes1e583132009-04-07 18:17:11 +020098 return &event;
99 }
Juan Cespedes1e583132009-04-07 18:17:11 +0200100 if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200101 event.type = EVENT_EXEC;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200102 debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
Juan Cespedes1e583132009-04-07 18:17:11 +0200103 return &event;
104 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100105 if (WIFEXITED(status)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200106 event.type = EVENT_EXIT;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100107 event.e_un.ret_val = WEXITSTATUS(status);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200108 debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100109 return &event;
110 }
111 if (WIFSIGNALED(status)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200112 event.type = EVENT_EXIT_SIGNAL;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100113 event.e_un.signum = WTERMSIG(status);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200114 debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100115 return &event;
116 }
117 if (!WIFSTOPPED(status)) {
Juan Cespedes427b7812009-07-06 23:05:30 +0200118 /* should never happen */
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200119 event.type = EVENT_NONE;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200120 debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100121 return &event;
122 }
Petr Machataef46b3e2007-05-09 19:21:42 +0200123
124 stop_signal = WSTOPSIG(status);
125
126 /* On some targets, breakpoints are signalled not using
127 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
Juan Cespedes427b7812009-07-06 23:05:30 +0200128 for these. (TODO: is this true?) */
Petr Machataef46b3e2007-05-09 19:21:42 +0200129 if (stop_signal == SIGSEGV
Juan Cespedes427b7812009-07-06 23:05:30 +0200130 || stop_signal == SIGILL
Petr Machataef46b3e2007-05-09 19:21:42 +0200131#ifdef SIGEMT
Juan Cespedes427b7812009-07-06 23:05:30 +0200132 || stop_signal == SIGEMT
Petr Machataef46b3e2007-05-09 19:21:42 +0200133#endif
Juan Cespedes427b7812009-07-06 23:05:30 +0200134 ) {
135 if (!event.proc->instruction_pointer) {
136 event.proc->instruction_pointer =
137 get_instruction_pointer(event.proc);
138 }
Petr Machataef46b3e2007-05-09 19:21:42 +0200139
Juan Cespedes427b7812009-07-06 23:05:30 +0200140 if (address2bpstruct(event.proc, event.proc->instruction_pointer))
Petr Machataef46b3e2007-05-09 19:21:42 +0200141 stop_signal = SIGTRAP;
142 }
143
144 if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
Juan Cespedes427b7812009-07-06 23:05:30 +0200145 && stop_signal != SIGTRAP) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200146 event.type = EVENT_SIGNAL;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200147 event.e_un.signum = stop_signal;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200148 debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100149 return &event;
150 }
Petr Machata55ed83b2007-05-17 16:24:15 +0200151
Juan Cespedes427b7812009-07-06 23:05:30 +0200152 /* last case [by exhaustion] */
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200153 event.type = EVENT_BREAKPOINT;
Juan Cespedes427b7812009-07-06 23:05:30 +0200154
Juan Cespedes35d70631998-03-15 14:05:40 +0100155 if (!event.proc->instruction_pointer) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100156 event.proc->instruction_pointer =
Juan Cespedes427b7812009-07-06 23:05:30 +0200157 get_instruction_pointer(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +0100158 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100159 event.e_un.brk_addr =
Juan Cespedes427b7812009-07-06 23:05:30 +0200160 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200161 debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100162 return &event;
163}