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