events.c revision 2721e6adbc7399e1b621b896b4f5b864082fbf03
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#define	_GNU_SOURCE	1
6#include <stdlib.h>
7#include <sys/types.h>
8#include <sys/wait.h>
9#include <errno.h>
10#include <signal.h>
11#include <string.h>
12#include <sys/ptrace.h>
13
14#include "ltrace.h"
15#include "options.h"
16#include "output.h"
17#include "debug.h"
18
19static Event event;
20
21Event *
22next_event(void) {
23	pid_t pid;
24	int status;
25	int tmp;
26	int stop_signal;
27
28	debug(DEBUG_FUNCTION, "next_event()");
29	if (!list_of_processes) {
30		debug(DEBUG_EVENT, "event: No more traced programs: exiting");
31		exit(0);
32	}
33	pid = wait(&status);
34	if (pid == -1) {
35		if (errno == ECHILD) {
36			debug(DEBUG_EVENT, "event: No more traced programs: exiting");
37			exit(0);
38		} else if (errno == EINTR) {
39			debug(DEBUG_EVENT, "event: none (wait received EINTR?)");
40			event.type = EVENT_NONE;
41			return &event;
42		}
43		perror("wait");
44		exit(1);
45	}
46	event.proc = pid2proc(pid);
47	if (!event.proc || event.proc->state == STATE_BEING_CREATED) {
48		event.type = EVENT_NEW;
49		event.e_un.newpid = pid;
50		debug(DEBUG_EVENT, "event: NEW: pid=%d", pid);
51		return &event;
52	}
53	get_arch_dep(event.proc);
54	event.proc->instruction_pointer = NULL;
55	debug(3, "event from pid %u", pid);
56	if (event.proc->breakpoints_enabled == -1) {
57		enable_all_breakpoints(event.proc);
58		event.type = EVENT_NONE;
59		trace_set_options(event.proc, event.proc->pid);
60		continue_process(event.proc->pid);
61		debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid);
62		return &event;
63	}
64	if (opt_i) {
65		event.proc->instruction_pointer =
66		    get_instruction_pointer(event.proc);
67	}
68	switch (syscall_p(event.proc, status, &tmp)) {
69		case 1:
70			event.type = EVENT_SYSCALL;
71			event.e_un.sysnum = tmp;
72			debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp);
73			return &event;
74		case 2:
75			event.type = EVENT_SYSRET;
76			event.e_un.sysnum = tmp;
77			debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp);
78			return &event;
79		case 3:
80			event.type = EVENT_ARCH_SYSCALL;
81			event.e_un.sysnum = tmp;
82			debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp);
83			return &event;
84		case 4:
85			event.type = EVENT_ARCH_SYSRET;
86			event.e_un.sysnum = tmp;
87			debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
88			return &event;
89		case -1:
90			event.type = EVENT_NONE;
91			continue_process(event.proc->pid);
92			debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
93			return &event;
94	}
95	if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
96		unsigned long data;
97		ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
98		event.type = EVENT_CLONE;
99		event.e_un.newpid = data;
100		debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data);
101		return &event;
102	}
103	if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
104		event.type = EVENT_EXEC;
105		debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
106		return &event;
107	}
108	if (WIFEXITED(status)) {
109		event.type = EVENT_EXIT;
110		event.e_un.ret_val = WEXITSTATUS(status);
111		debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
112		return &event;
113	}
114	if (WIFSIGNALED(status)) {
115		event.type = EVENT_EXIT_SIGNAL;
116		event.e_un.signum = WTERMSIG(status);
117		debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
118		return &event;
119	}
120	if (!WIFSTOPPED(status)) {
121		event.type = EVENT_NONE;
122		debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid);
123		return &event;
124	}
125
126	stop_signal = WSTOPSIG(status);
127
128	/* On some targets, breakpoints are signalled not using
129	   SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT.  Check
130	   for these. */
131	if (stop_signal == SIGSEGV
132	    || stop_signal == SIGILL
133#ifdef SIGEMT
134	    || stop_signal == SIGEMT
135#endif
136	    ) {
137		// If we didn't need to know IP so far, get it now.
138		void * addr = opt_i
139		  ? event.proc->instruction_pointer
140		  : (event.proc->instruction_pointer = get_instruction_pointer (event.proc));
141
142		if (address2bpstruct(event.proc, addr))
143			stop_signal = SIGTRAP;
144	}
145
146	if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
147	    && stop_signal != SIGTRAP) {
148		event.type = EVENT_SIGNAL;
149		event.e_un.signum = stop_signal;
150		debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal);
151		return &event;
152	}
153
154	if (was_exec(event.proc, status)) {
155		pid_t saved_pid;
156
157		event.type = EVENT_NONE;
158		event.e_un.signum = WSTOPSIG(status);
159		debug(1, "Placing breakpoints for the new program");
160		event.proc->mask_32bit = 0;
161		event.proc->personality = 0;
162		event.proc->arch_ptr = NULL;
163		event.proc->filename = pid2name(event.proc->pid);
164		saved_pid = event.proc->pid;
165		event.proc->pid = 0;
166		breakpoints_init(event.proc);
167		event.proc->pid = saved_pid;
168		continue_process(event.proc->pid);
169		debug(DEBUG_EVENT, "event: NONE: pid=%d (was_exec; placed breakpoints)", pid);
170		return &event;
171	}
172
173	event.type = EVENT_BREAKPOINT;
174	if (!event.proc->instruction_pointer) {
175		event.proc->instruction_pointer =
176		    get_instruction_pointer(event.proc);
177	}
178	event.e_un.brk_addr =
179	    event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
180	debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr);
181	return &event;
182}
183