handle_event.c revision 98f0992f9c3fd5da41a4928407251d9f5a837702
1#include "config.h"
2
3#define _GNU_SOURCE
4#include <stdio.h>
5#include <string.h>
6#include <stdlib.h>
7#include <signal.h>
8#include <assert.h>
9#include <sys/time.h>
10
11#include "common.h"
12
13#ifdef __powerpc__
14#include <sys/ptrace.h>
15#endif
16
17static void handle_signal(Event *event);
18static void handle_exit(Event *event);
19static void handle_exit_signal(Event *event);
20static void handle_syscall(Event *event);
21static void handle_arch_syscall(Event *event);
22static void handle_sysret(Event *event);
23static void handle_arch_sysret(Event *event);
24static void handle_clone(Event *event);
25static void handle_exec(Event *event);
26static void handle_breakpoint(Event *event);
27static void handle_new(Event *event);
28
29static void callstack_push_syscall(Process *proc, int sysnum);
30static void callstack_push_symfunc(Process *proc,
31				   struct library_symbol *sym);
32static void callstack_pop(Process *proc);
33
34static char * shortsignal(Process *proc, int signum);
35static char * sysname(Process *proc, int sysnum);
36static char * arch_sysname(Process *proc, int sysnum);
37
38void
39handle_event(Event *event) {
40	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
41	      event->proc ? event->proc->pid : -1, event->type);
42	/* If the thread group defines an overriding event handler,
43	   give it a chance to kick in.  */
44	if (event->proc != NULL
45	    && event->proc->leader != NULL) {
46		Event_Handler * handler = event->proc->leader->event_handler;
47		if (handler != NULL) {
48			event = (*handler->on_event) (handler, event);
49			if (event == NULL)
50				/* It was handled.  */
51				return;
52		}
53	}
54
55	switch (event->type) {
56	case EVENT_NONE:
57		debug(1, "event: none");
58		return;
59	case EVENT_SIGNAL:
60		debug(1, "event: signal (%s [%d])",
61		      shortsignal(event->proc, event->e_un.signum),
62		      event->e_un.signum);
63		handle_signal(event);
64		return;
65	case EVENT_EXIT:
66		debug(1, "event: exit (%d)", event->e_un.ret_val);
67		handle_exit(event);
68		return;
69	case EVENT_EXIT_SIGNAL:
70		debug(1, "event: exit signal (%s [%d])",
71		      shortsignal(event->proc, event->e_un.signum),
72		      event->e_un.signum);
73		handle_exit_signal(event);
74		return;
75	case EVENT_SYSCALL:
76		debug(1, "event: syscall (%s [%d])",
77		      sysname(event->proc, event->e_un.sysnum),
78		      event->e_un.sysnum);
79		handle_syscall(event);
80		return;
81	case EVENT_SYSRET:
82		debug(1, "event: sysret (%s [%d])",
83		      sysname(event->proc, event->e_un.sysnum),
84		      event->e_un.sysnum);
85		handle_sysret(event);
86		return;
87	case EVENT_ARCH_SYSCALL:
88		debug(1, "event: arch_syscall (%s [%d])",
89				arch_sysname(event->proc, event->e_un.sysnum),
90				event->e_un.sysnum);
91		handle_arch_syscall(event);
92		return;
93	case EVENT_ARCH_SYSRET:
94		debug(1, "event: arch_sysret (%s [%d])",
95				arch_sysname(event->proc, event->e_un.sysnum),
96				event->e_un.sysnum);
97		handle_arch_sysret(event);
98		return;
99	case EVENT_CLONE:
100		debug(1, "event: clone (%u)", event->e_un.newpid);
101		handle_clone(event);
102		return;
103	case EVENT_EXEC:
104		debug(1, "event: exec()");
105		handle_exec(event);
106		return;
107	case EVENT_BREAKPOINT:
108		debug(1, "event: breakpoint");
109		handle_breakpoint(event);
110		return;
111	case EVENT_NEW:
112		debug(1, "event: new process");
113		handle_new(event);
114		return;
115	default:
116		fprintf(stderr, "Error! unknown event?\n");
117		exit(1);
118	}
119}
120
121/* TODO */
122static void *
123address_clone(void * addr) {
124	debug(DEBUG_FUNCTION, "address_clone(%p)", addr);
125	return addr;
126}
127
128static void *
129breakpoint_clone(void * bp) {
130	Breakpoint * b;
131	debug(DEBUG_FUNCTION, "breakpoint_clone(%p)", bp);
132	b = malloc(sizeof(Breakpoint));
133	if (!b) {
134		perror("malloc()");
135		exit(1);
136	}
137	memcpy(b, bp, sizeof(Breakpoint));
138	return b;
139}
140
141typedef struct Pending_New Pending_New;
142struct Pending_New {
143	pid_t pid;
144	Pending_New * next;
145};
146static Pending_New * pending_news = NULL;
147
148static int
149pending_new(pid_t pid) {
150	Pending_New * p;
151
152	debug(DEBUG_FUNCTION, "pending_new(%d)", pid);
153
154	p = pending_news;
155	while (p) {
156		if (p->pid == pid) {
157			return 1;
158		}
159		p = p->next;
160	}
161	return 0;
162}
163
164static void
165pending_new_insert(pid_t pid) {
166	Pending_New * p;
167
168	debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid);
169
170	p = malloc(sizeof(Pending_New));
171	if (!p) {
172		perror("malloc()");
173		exit(1);
174	}
175	p->pid = pid;
176	p->next = pending_news;
177	pending_news = p;
178}
179
180static void
181pending_new_remove(pid_t pid) {
182	Pending_New *p, *pred;
183
184	debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid);
185
186	p = pending_news;
187	if (p->pid == pid) {
188		pending_news = p->next;
189		free(p);
190	} else {
191		while (p) {
192			if (p->pid == pid) {
193				pred->next = p->next;
194				free(p);
195			}
196			pred = p;
197			p = p->next;
198		}
199	}
200}
201
202static void
203handle_clone(Event * event) {
204	Process *p;
205
206	debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid);
207
208	p = malloc(sizeof(Process));
209	if (!p) {
210		perror("malloc()");
211		exit(1);
212	}
213	memcpy(p, event->proc, sizeof(Process));
214	p->breakpoints = dict_clone(event->proc->breakpoints, address_clone, breakpoint_clone);
215	p->pid = event->e_un.newpid;
216	p->parent = event->proc;
217
218	if (pending_new(p->pid)) {
219		pending_new_remove(p->pid);
220		if (p->event_handler != NULL)
221			destroy_event_handler(p);
222		if (event->proc->state == STATE_ATTACHED && options.follow) {
223			p->state = STATE_ATTACHED;
224		} else {
225			p->state = STATE_IGNORED;
226		}
227		continue_process(p->pid);
228		add_process(p);
229	} else {
230		p->state = STATE_BEING_CREATED;
231		add_process(p);
232	}
233	continue_process(event->proc->pid);
234}
235
236static void
237handle_new(Event * event) {
238	Process * proc;
239
240	debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid);
241
242	proc = pid2proc(event->e_un.newpid);
243	if (!proc) {
244		pending_new_insert(event->e_un.newpid);
245	} else {
246		assert(proc->state == STATE_BEING_CREATED);
247		if (proc->event_handler != NULL)
248			destroy_event_handler(proc);
249		if (options.follow) {
250			proc->state = STATE_ATTACHED;
251		} else {
252			proc->state = STATE_IGNORED;
253		}
254		continue_process(proc->pid);
255	}
256}
257
258static char *
259shortsignal(Process *proc, int signum) {
260	static char *signalent0[] = {
261#include "signalent.h"
262	};
263	static char *signalent1[] = {
264#include "signalent1.h"
265	};
266	static char **signalents[] = { signalent0, signalent1 };
267	int nsignals[] = { sizeof signalent0 / sizeof signalent0[0],
268		sizeof signalent1 / sizeof signalent1[0]
269	};
270
271	debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum);
272
273	if (proc->personality > sizeof signalents / sizeof signalents[0])
274		abort();
275	if (signum < 0 || signum >= nsignals[proc->personality]) {
276		return "UNKNOWN_SIGNAL";
277	} else {
278		return signalents[proc->personality][signum];
279	}
280}
281
282static char *
283sysname(Process *proc, int sysnum) {
284	static char result[128];
285	static char *syscalent0[] = {
286#include "syscallent.h"
287	};
288	static char *syscalent1[] = {
289#include "syscallent1.h"
290	};
291	static char **syscalents[] = { syscalent0, syscalent1 };
292	int nsyscals[] = { sizeof syscalent0 / sizeof syscalent0[0],
293		sizeof syscalent1 / sizeof syscalent1[0]
294	};
295
296	debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
297
298	if (proc->personality > sizeof syscalents / sizeof syscalents[0])
299		abort();
300	if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) {
301		sprintf(result, "SYS_%d", sysnum);
302		return result;
303	} else {
304		sprintf(result, "SYS_%s",
305			syscalents[proc->personality][sysnum]);
306		return result;
307	}
308}
309
310static char *
311arch_sysname(Process *proc, int sysnum) {
312	static char result[128];
313	static char *arch_syscalent[] = {
314#include "arch_syscallent.h"
315	};
316	int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0];
317
318	debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
319
320	if (sysnum < 0 || sysnum >= nsyscals) {
321		sprintf(result, "ARCH_%d", sysnum);
322		return result;
323	} else {
324		sprintf(result, "ARCH_%s",
325				arch_syscalent[sysnum]);
326		return result;
327	}
328}
329
330static void
331handle_signal(Event *event) {
332	debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
333	if (exiting && event->e_un.signum == SIGSTOP) {
334		pid_t pid = event->proc->pid;
335		disable_all_breakpoints(event->proc);
336		untrace_pid(pid);
337		remove_process(event->proc);
338		return;
339	}
340	if (event->proc->state != STATE_IGNORED && !options.no_signals) {
341		output_line(event->proc, "--- %s (%s) ---",
342				shortsignal(event->proc, event->e_un.signum),
343				strsignal(event->e_un.signum));
344	}
345	continue_after_signal(event->proc->pid, event->e_un.signum);
346}
347
348static void
349handle_exit(Event *event) {
350	debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
351	if (event->proc->state != STATE_IGNORED) {
352		output_line(event->proc, "+++ exited (status %d) +++",
353				event->e_un.ret_val);
354	}
355	remove_process(event->proc);
356}
357
358static void
359handle_exit_signal(Event *event) {
360	debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
361	if (event->proc->state != STATE_IGNORED) {
362		output_line(event->proc, "+++ killed by %s +++",
363				shortsignal(event->proc, event->e_un.signum));
364	}
365	remove_process(event->proc);
366}
367
368static void
369handle_syscall(Event *event) {
370	debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
371	if (event->proc->state != STATE_IGNORED) {
372		callstack_push_syscall(event->proc, event->e_un.sysnum);
373		if (options.syscalls) {
374			output_left(LT_TOF_SYSCALL, event->proc,
375				    sysname(event->proc, event->e_un.sysnum));
376		}
377		if (event->proc->breakpoints_enabled == 0) {
378			enable_all_breakpoints(event->proc);
379		}
380	}
381	continue_process(event->proc->pid);
382}
383
384static void
385handle_exec(Event * event) {
386	Process * proc = event->proc;
387	pid_t saved_pid;
388
389	debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid);
390	if (proc->state == STATE_IGNORED) {
391		untrace_pid(proc->pid);
392		remove_process(proc);
393		return;
394	}
395	output_line(proc, "--- Called exec() ---");
396	proc->mask_32bit = 0;
397	proc->personality = 0;
398	proc->arch_ptr = NULL;
399	free(proc->filename);
400	proc->filename = pid2name(proc->pid);
401	saved_pid = proc->pid;
402	proc->pid = 0;
403	breakpoints_init(proc, 0);
404	proc->pid = saved_pid;
405	proc->callstack_depth = 0;
406	continue_process(proc->pid);
407}
408
409static void
410handle_arch_syscall(Event *event) {
411	debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
412	if (event->proc->state != STATE_IGNORED) {
413		callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
414		if (options.syscalls) {
415			output_left(LT_TOF_SYSCALL, event->proc,
416					arch_sysname(event->proc, event->e_un.sysnum));
417		}
418		if (event->proc->breakpoints_enabled == 0) {
419			enable_all_breakpoints(event->proc);
420		}
421	}
422	continue_process(event->proc->pid);
423}
424
425struct timeval current_time_spent;
426
427static void
428calc_time_spent(Process *proc) {
429	struct timeval tv;
430	struct timezone tz;
431	struct timeval diff;
432	struct callstack_element *elem;
433
434	debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid);
435	elem = &proc->callstack[proc->callstack_depth - 1];
436
437	gettimeofday(&tv, &tz);
438
439	diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec;
440	if (tv.tv_usec >= elem->time_spent.tv_usec) {
441		diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec;
442	} else {
443		diff.tv_sec++;
444		diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
445	}
446	current_time_spent = diff;
447}
448
449static void
450handle_sysret(Event *event) {
451	debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
452	if (event->proc->state != STATE_IGNORED) {
453		if (opt_T || options.summary) {
454			calc_time_spent(event->proc);
455		}
456		if (options.syscalls) {
457			output_right(LT_TOF_SYSCALLR, event->proc,
458					sysname(event->proc, event->e_un.sysnum));
459		}
460		callstack_pop(event->proc);
461	}
462	continue_process(event->proc->pid);
463}
464
465static void
466handle_arch_sysret(Event *event) {
467	debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
468	if (event->proc->state != STATE_IGNORED) {
469		if (opt_T || options.summary) {
470			calc_time_spent(event->proc);
471		}
472		if (options.syscalls) {
473			output_right(LT_TOF_SYSCALLR, event->proc,
474					arch_sysname(event->proc, event->e_un.sysnum));
475		}
476		callstack_pop(event->proc);
477	}
478	continue_process(event->proc->pid);
479}
480
481#ifdef __powerpc__
482void *get_count_register (Process *proc);
483#endif
484
485static void
486handle_breakpoint(Event *event) {
487	int i, j;
488	Breakpoint *sbp;
489	Process *leader = event->proc->leader;
490
491	/* The leader has terminated.  */
492	if (leader == NULL) {
493		continue_process(event->proc->pid);
494		return;
495	}
496
497	debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", event->proc->pid, event->e_un.brk_addr);
498	debug(2, "event: breakpoint (%p)", event->e_un.brk_addr);
499
500#ifdef __powerpc__
501	/* Need to skip following NOP's to prevent a fake function from being stacked.  */
502	long stub_addr = (long) get_count_register(event->proc);
503	Breakpoint *stub_bp = NULL;
504	char nop_instruction[] = PPC_NOP;
505
506	stub_bp = address2bpstruct(leader, event->e_un.brk_addr);
507
508	if (stub_bp) {
509		unsigned char *bp_instruction = stub_bp->orig_value;
510
511		if (memcmp(bp_instruction, nop_instruction,
512			    PPC_NOP_LENGTH) == 0) {
513			if (stub_addr != (long) event->e_un.brk_addr) {
514				set_instruction_pointer (event->proc, event->e_un.brk_addr + 4);
515				continue_process(event->proc->pid);
516				return;
517			}
518		}
519	}
520#endif
521
522	for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
523		if (event->e_un.brk_addr ==
524		    event->proc->callstack[i].return_addr) {
525#ifdef __powerpc__
526			/*
527			 * PPC HACK! (XXX FIXME TODO)
528			 * The PLT gets modified during the first call,
529			 * so be sure to re-enable the breakpoint.
530			 */
531			unsigned long a;
532			struct library_symbol *libsym =
533			    event->proc->callstack[i].c_un.libfunc;
534			void *addr = sym2addr(event->proc, libsym);
535
536			if (libsym->plt_type != LS_TOPLT_POINT) {
537				unsigned char break_insn[] = BREAKPOINT_VALUE;
538
539				sbp = address2bpstruct(leader, addr);
540				assert(sbp);
541				a = ptrace(PTRACE_PEEKTEXT, event->proc->pid,
542					   addr);
543
544				if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) {
545					sbp->enabled--;
546					insert_breakpoint(event->proc, addr,
547							  libsym);
548				}
549			} else {
550				sbp = dict_find_entry(leader->breakpoints, addr);
551				/* On powerpc, the breakpoint address
552				   may end up being actual entry point
553				   of the library symbol, not the PLT
554				   address we computed.  In that case,
555				   sbp is NULL.  */
556				if (sbp == NULL || addr != sbp->addr) {
557					insert_breakpoint(event->proc, addr,
558							  libsym);
559				}
560			}
561#elif defined(__mips__)
562			void *addr = NULL;
563			struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
564			struct library_symbol *new_sym;
565			assert(sym);
566			addr = sym2addr(leader, sym);
567			sbp = dict_find_entry(leader->breakpoints, addr);
568			if (sbp) {
569				if (addr != sbp->addr) {
570					insert_breakpoint(event->proc, addr, sym);
571				}
572			} else {
573				new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
574				memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
575				new_sym->next = leader->list_of_symbols;
576				leader->list_of_symbols = new_sym;
577				insert_breakpoint(event->proc, addr, new_sym);
578			}
579#endif
580			for (j = event->proc->callstack_depth - 1; j > i; j--) {
581				callstack_pop(event->proc);
582			}
583			if (event->proc->state != STATE_IGNORED) {
584				if (opt_T || options.summary) {
585					calc_time_spent(event->proc);
586				}
587			}
588			event->proc->return_addr = event->e_un.brk_addr;
589			if (event->proc->state != STATE_IGNORED) {
590				output_right(LT_TOF_FUNCTIONR, event->proc,
591						event->proc->callstack[i].c_un.libfunc->name);
592			}
593			callstack_pop(event->proc);
594			sbp = address2bpstruct(leader, event->e_un.brk_addr);
595			continue_after_breakpoint(event->proc, sbp);
596			return;
597		}
598	}
599
600	if ((sbp = address2bpstruct(leader, event->e_un.brk_addr))) {
601		if (sbp->libsym == NULL) {
602			continue_after_breakpoint(event->proc, sbp);
603			return;
604		}
605
606		if (strcmp(sbp->libsym->name, "") == 0) {
607			debug(DEBUG_PROCESS, "Hit _dl_debug_state breakpoint!\n");
608			arch_check_dbg(leader);
609		}
610
611		if (event->proc->state != STATE_IGNORED) {
612			event->proc->stack_pointer = get_stack_pointer(event->proc);
613			event->proc->return_addr =
614				get_return_addr(event->proc, event->proc->stack_pointer);
615			callstack_push_symfunc(event->proc, sbp->libsym);
616			output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name);
617		}
618#ifdef PLT_REINITALISATION_BP
619		if (event->proc->need_to_reinitialize_breakpoints
620		    && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) ==
621			0))
622			reinitialize_breakpoints(leader);
623#endif
624
625		continue_after_breakpoint(event->proc, sbp);
626		return;
627	}
628
629	if (event->proc->state != STATE_IGNORED && !options.no_plt) {
630		output_line(event->proc, "unexpected breakpoint at %p",
631				(void *)event->e_un.brk_addr);
632	}
633	continue_process(event->proc->pid);
634}
635
636static void
637callstack_push_syscall(Process *proc, int sysnum) {
638	struct callstack_element *elem;
639
640	debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum);
641	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
642	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
643		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
644		abort();
645		return;
646	}
647
648	elem = &proc->callstack[proc->callstack_depth];
649	elem->is_syscall = 1;
650	elem->c_un.syscall = sysnum;
651	elem->return_addr = NULL;
652
653	proc->callstack_depth++;
654	if (opt_T || options.summary) {
655		struct timezone tz;
656		gettimeofday(&elem->time_spent, &tz);
657	}
658}
659
660static void
661callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
662	struct callstack_element *elem, *prev;
663
664	debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name);
665	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
666	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
667		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
668		abort();
669		return;
670	}
671
672	prev = &proc->callstack[proc->callstack_depth-1];
673	elem = &proc->callstack[proc->callstack_depth];
674	elem->is_syscall = 0;
675	elem->c_un.libfunc = sym;
676
677	elem->return_addr = proc->return_addr;
678	if (elem->return_addr) {
679		insert_breakpoint(proc, elem->return_addr, NULL, 1);
680	}
681
682	/* handle functions like atexit() on mips which have no return */
683	if (elem->return_addr != prev->return_addr)
684		proc->callstack_depth++;
685	if (opt_T || options.summary) {
686		struct timezone tz;
687		gettimeofday(&elem->time_spent, &tz);
688	}
689}
690
691static void
692callstack_pop(Process *proc) {
693	struct callstack_element *elem;
694	assert(proc->callstack_depth > 0);
695
696	debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid);
697	elem = &proc->callstack[proc->callstack_depth - 1];
698	if (!elem->is_syscall && elem->return_addr) {
699		assert(proc->leader != NULL);
700		delete_breakpoint(proc, elem->return_addr);
701	}
702	if (elem->arch_ptr != NULL) {
703		free(elem->arch_ptr);
704		elem->arch_ptr = NULL;
705	}
706	proc->callstack_depth--;
707}
708