events.c revision cebb88491e68bdf4d466b03970c9ca77f65615f8
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	event.proc->instruction_pointer = NULL;
57	debug(3, "event from pid %u", pid);
58	if (event.proc->breakpoints_enabled == -1) {
59		event.type = EVENT_NONE;
60		trace_set_options(event.proc, event.proc->pid);
61		enable_all_breakpoints(event.proc);
62		continue_process(event.proc->pid);
63		debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid);
64		return &event;
65	} else if (!event.proc->libdl_hooked) {
66		/* debug struct may not have been written yet.. */
67		if (linkmap_init(event.proc, &main_lte) == 0) {
68			event.proc->libdl_hooked = 1;
69		}
70	}
71
72
73	event.proc->instruction_pointer = get_instruction_pointer(event.proc);
74	if (event.proc->instruction_pointer == (void *)(uintptr_t)-1) {
75		if (errno != 0)
76			perror("get_instruction_pointer");
77	}
78
79	switch (syscall_p(event.proc, status, &tmp)) {
80		case 1:
81			event.type = EVENT_SYSCALL;
82			event.e_un.sysnum = tmp;
83			debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp);
84			return &event;
85		case 2:
86			event.type = EVENT_SYSRET;
87			event.e_un.sysnum = tmp;
88			debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp);
89			return &event;
90		case 3:
91			event.type = EVENT_ARCH_SYSCALL;
92			event.e_un.sysnum = tmp;
93			debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp);
94			return &event;
95		case 4:
96			event.type = EVENT_ARCH_SYSRET;
97			event.e_un.sysnum = tmp;
98			debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
99			return &event;
100		case -1:
101			event.type = EVENT_NONE;
102			continue_process(event.proc->pid);
103			debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
104			return &event;
105	}
106	if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
107		unsigned long data;
108		ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
109		event.type = EVENT_CLONE;
110		event.e_un.newpid = data;
111		debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data);
112		return &event;
113	}
114	if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
115		event.type = EVENT_EXEC;
116		debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
117		return &event;
118	}
119	if (WIFEXITED(status)) {
120		event.type = EVENT_EXIT;
121		event.e_un.ret_val = WEXITSTATUS(status);
122		debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
123		return &event;
124	}
125	if (WIFSIGNALED(status)) {
126		event.type = EVENT_EXIT_SIGNAL;
127		event.e_un.signum = WTERMSIG(status);
128		debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
129		return &event;
130	}
131	if (!WIFSTOPPED(status)) {
132		/* should never happen */
133		event.type = EVENT_NONE;
134		debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid);
135		return &event;
136	}
137
138	stop_signal = WSTOPSIG(status);
139
140	/* On some targets, breakpoints are signalled not using
141	   SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT.  SIGEMT
142	   is not defined on Linux, but check for the others.
143
144	   N.B. see comments in GDB's infrun.c for details.  I've
145	   actually seen this on an Itanium machine on RHEL 5, I don't
146	   remember the exact kernel version anymore.  ia64-sigill.s
147	   in the test suite tests this.  Petr Machata 2011-06-08.  */
148	void * break_address
149		= event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
150	if ((stop_signal == SIGSEGV || stop_signal == SIGILL)
151	    && address2bpstruct(event.proc, break_address))
152			stop_signal = SIGTRAP;
153
154	if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
155			&& stop_signal != SIGTRAP) {
156		event.type = EVENT_SIGNAL;
157		event.e_un.signum = stop_signal;
158		debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal);
159		return &event;
160	}
161
162	/* last case [by exhaustion] */
163	event.type = EVENT_BREAKPOINT;
164
165	event.e_un.brk_addr = break_address;
166	debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr);
167
168	return &event;
169}
170