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