handle_event.c revision ba4734098037555614b1ce6458b3f18415764f4a
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4 * Copyright (C) 2010 Arnaud Patard, Mandriva SA
5 * Copyright (C) 1998,2001,2002,2003,2004,2007,2008,2009 Juan Cespedes
6 * Copyright (C) 2008 Luis Machado, IBM Corporation
7 * Copyright (C) 2006 Ian Wienand
8 * Copyright (C) 2006 Paul Gilliam, IBM Corporation
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 */
25
26#include "config.h"
27
28#define _GNU_SOURCE
29#include <assert.h>
30#include <errno.h>
31#include <signal.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/time.h>
36#include <stdbool.h>
37
38#include "backend.h"
39#include "breakpoint.h"
40#include "common.h"
41#include "fetch.h"
42#include "library.h"
43#include "proc.h"
44#include "value_dict.h"
45#include "prototype.h"
46
47static void handle_signal(Event *event);
48static void handle_exit(Event *event);
49static void handle_exit_signal(Event *event);
50static void handle_syscall(Event *event);
51static void handle_arch_syscall(Event *event);
52static void handle_sysret(Event *event);
53static void handle_arch_sysret(Event *event);
54static void handle_clone(Event *event);
55static void handle_exec(Event *event);
56static void handle_breakpoint(Event *event);
57static void handle_new(Event *event);
58
59static void callstack_push_syscall(struct process *proc, int sysnum);
60static void callstack_push_symfunc(struct process *proc, struct breakpoint *bp);
61/* XXX Stack maintenance should be moved to a dedicated module, or to
62 * proc.c, and push/pop should be visible outside this module.  For
63 * now, because we need this in proc.c, this is non-static.  */
64void callstack_pop(struct process *proc);
65
66static char *shortsignal(struct process *proc, int signum);
67static char *sysname(struct process *proc, int sysnum);
68static char *arch_sysname(struct process *proc, int sysnum);
69
70static Event *
71call_handler(struct process *proc, Event *event)
72{
73	assert(proc != NULL);
74
75	struct event_handler *handler = proc->event_handler;
76	if (handler == NULL)
77		return event;
78
79	return (*handler->on_event) (handler, event);
80}
81
82void
83handle_event(Event *event)
84{
85	if (exiting == 1) {
86		debug(1, "ltrace about to exit");
87		os_ltrace_exiting();
88		exiting = 2;
89	}
90	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
91	      event->proc ? event->proc->pid : -1, event->type);
92
93	/* If the thread group or an individual task define an
94	   overriding event handler, give them a chance to kick in.
95	   We will end up calling both handlers, if the first one
96	   doesn't sink the event.  */
97	if (event->proc != NULL) {
98		event = call_handler(event->proc, event);
99		if (event == NULL)
100			/* It was handled.  */
101			return;
102
103		/* Note: the previous handler has a chance to alter
104		 * the event.  */
105		if (event->proc != NULL
106		    && event->proc->leader != NULL
107		    && event->proc != event->proc->leader) {
108			event = call_handler(event->proc->leader, event);
109			if (event == NULL)
110				return;
111		}
112	}
113
114	switch (event->type) {
115	case EVENT_NONE:
116		debug(1, "event: none");
117		return;
118
119	case EVENT_SIGNAL:
120		assert(event->proc != NULL);
121		debug(1, "[%d] event: signal (%s [%d])",
122		      event->proc->pid,
123		      shortsignal(event->proc, event->e_un.signum),
124		      event->e_un.signum);
125		handle_signal(event);
126		return;
127
128	case EVENT_EXIT:
129		assert(event->proc != NULL);
130		debug(1, "[%d] event: exit (%d)",
131		      event->proc->pid,
132		      event->e_un.ret_val);
133		handle_exit(event);
134		return;
135
136	case EVENT_EXIT_SIGNAL:
137		assert(event->proc != NULL);
138		debug(1, "[%d] event: exit signal (%s [%d])",
139		      event->proc->pid,
140		      shortsignal(event->proc, event->e_un.signum),
141		      event->e_un.signum);
142		handle_exit_signal(event);
143		return;
144
145	case EVENT_SYSCALL:
146		assert(event->proc != NULL);
147		debug(1, "[%d] event: syscall (%s [%d])",
148		      event->proc->pid,
149		      sysname(event->proc, event->e_un.sysnum),
150		      event->e_un.sysnum);
151		handle_syscall(event);
152		return;
153
154	case EVENT_SYSRET:
155		assert(event->proc != NULL);
156		debug(1, "[%d] event: sysret (%s [%d])",
157		      event->proc->pid,
158		      sysname(event->proc, event->e_un.sysnum),
159		      event->e_un.sysnum);
160		handle_sysret(event);
161		return;
162
163	case EVENT_ARCH_SYSCALL:
164		assert(event->proc != NULL);
165		debug(1, "[%d] event: arch_syscall (%s [%d])",
166		      event->proc->pid,
167		      arch_sysname(event->proc, event->e_un.sysnum),
168		      event->e_un.sysnum);
169		handle_arch_syscall(event);
170		return;
171
172	case EVENT_ARCH_SYSRET:
173		assert(event->proc != NULL);
174		debug(1, "[%d] event: arch_sysret (%s [%d])",
175		      event->proc->pid,
176		      arch_sysname(event->proc, event->e_un.sysnum),
177		      event->e_un.sysnum);
178		handle_arch_sysret(event);
179		return;
180
181	case EVENT_CLONE:
182	case EVENT_VFORK:
183		assert(event->proc != NULL);
184		debug(1, "[%d] event: clone (%u)",
185		      event->proc->pid, event->e_un.newpid);
186		handle_clone(event);
187		return;
188
189	case EVENT_EXEC:
190		assert(event->proc != NULL);
191		debug(1, "[%d] event: exec()",
192		      event->proc->pid);
193		handle_exec(event);
194		return;
195
196	case EVENT_BREAKPOINT:
197		assert(event->proc != NULL);
198		debug(1, "[%d] event: breakpoint %p",
199		      event->proc->pid, event->e_un.brk_addr);
200		handle_breakpoint(event);
201		return;
202
203	case EVENT_NEW:
204		debug(1, "[%d] event: new process",
205		      event->e_un.newpid);
206		handle_new(event);
207		return;
208	default:
209		fprintf(stderr, "Error! unknown event?\n");
210		exit(1);
211	}
212}
213
214typedef struct Pending_New Pending_New;
215struct Pending_New {
216	pid_t pid;
217	Pending_New * next;
218};
219static Pending_New * pending_news = NULL;
220
221static int
222pending_new(pid_t pid) {
223	Pending_New * p;
224
225	debug(DEBUG_FUNCTION, "pending_new(%d)", pid);
226
227	p = pending_news;
228	while (p) {
229		if (p->pid == pid) {
230			return 1;
231		}
232		p = p->next;
233	}
234	return 0;
235}
236
237static void
238pending_new_insert(pid_t pid) {
239	Pending_New * p;
240
241	debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid);
242
243	p = malloc(sizeof(Pending_New));
244	if (!p) {
245		perror("malloc()");
246		exit(1);
247	}
248	p->pid = pid;
249	p->next = pending_news;
250	pending_news = p;
251}
252
253static void
254pending_new_remove(pid_t pid)
255{
256	debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid);
257
258	Pending_New **pp;
259	for (pp = &pending_news; *pp != NULL; pp = &(*pp)->next)
260		if ((*pp)->pid == pid) {
261			Pending_New *p = *pp;
262			*pp = p->next;
263			free(p);
264			return;
265		}
266}
267
268static void
269handle_clone(Event *event)
270{
271	debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid);
272
273	struct process *proc = malloc(sizeof(*proc));
274	pid_t newpid = event->e_un.newpid;
275	if (proc == NULL
276	    || process_clone(proc, event->proc, newpid) < 0) {
277		free(proc);
278		proc = NULL;
279		fprintf(stderr,
280			"Couldn't initialize tracing of process %d.\n",
281			newpid);
282
283	} else {
284		proc->parent = event->proc;
285		/* We save register values to the arch pointer, and
286		 * these need to be per-thread.  XXX arch_ptr should
287		 * be retired in favor of fetch interface anyway.  */
288		proc->arch_ptr = NULL;
289	}
290
291	if (pending_new(newpid)) {
292		pending_new_remove(newpid);
293
294		if (proc != NULL) {
295			proc->event_handler = NULL;
296			if (event->proc->state == STATE_ATTACHED
297			    && options.follow)
298				proc->state = STATE_ATTACHED;
299			else
300				proc->state = STATE_IGNORED;
301		}
302
303		continue_process(newpid);
304
305	} else if (proc != NULL) {
306		proc->state = STATE_BEING_CREATED;
307	}
308
309	if (event->type != EVENT_VFORK)
310		continue_process(event->proc->pid);
311	else if (proc != NULL)
312		continue_after_vfork(proc);
313	else
314		continue_process(newpid);
315}
316
317static void
318handle_new(Event *event)
319{
320	debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid);
321
322	struct process *proc = pid2proc(event->e_un.newpid);
323	if (!proc) {
324		pending_new_insert(event->e_un.newpid);
325	} else {
326		assert(proc->state == STATE_BEING_CREATED);
327		if (options.follow) {
328			proc->state = STATE_ATTACHED;
329		} else {
330			proc->state = STATE_IGNORED;
331		}
332		continue_process(proc->pid);
333	}
334}
335
336static char *
337shortsignal(struct process *proc, int signum)
338{
339	static char *signalent0[] = {
340#include "signalent.h"
341	};
342	static char *signalent1[] = {
343#include "signalent1.h"
344	};
345	static char **signalents[] = { signalent0, signalent1 };
346	int nsignals[] = { sizeof signalent0 / sizeof signalent0[0],
347		sizeof signalent1 / sizeof signalent1[0]
348	};
349
350	debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum);
351
352	assert(proc->personality < sizeof signalents / sizeof signalents[0]);
353	if (signum < 0 || signum >= nsignals[proc->personality]) {
354		return "UNKNOWN_SIGNAL";
355	} else {
356		return signalents[proc->personality][signum];
357	}
358}
359
360static char *
361sysname(struct process *proc, int sysnum)
362{
363	static char result[128];
364	static char *syscallent0[] = {
365#include "syscallent.h"
366	};
367	static char *syscallent1[] = {
368#include "syscallent1.h"
369	};
370	static char **syscallents[] = { syscallent0, syscallent1 };
371	int nsyscalls[] = {
372		sizeof syscallent0 / sizeof syscallent0[0],
373		sizeof syscallent1 / sizeof syscallent1[0],
374	};
375
376	debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
377
378	assert(proc->personality < sizeof syscallents / sizeof syscallents[0]);
379	if (sysnum < 0 || sysnum >= nsyscalls[proc->personality]) {
380		sprintf(result, "SYS_%d", sysnum);
381		return result;
382	} else {
383		return syscallents[proc->personality][sysnum];
384	}
385}
386
387static char *
388arch_sysname(struct process *proc, int sysnum)
389{
390	static char result[128];
391	static char *arch_syscallent[] = {
392#include "arch_syscallent.h"
393	};
394	int nsyscalls = sizeof arch_syscallent / sizeof arch_syscallent[0];
395
396	debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
397
398	if (sysnum < 0 || sysnum >= nsyscalls) {
399		sprintf(result, "ARCH_%d", sysnum);
400		return result;
401	} else {
402		sprintf(result, "ARCH_%s", arch_syscallent[sysnum]);
403		return result;
404	}
405}
406
407#ifndef HAVE_STRSIGNAL
408# define strsignal(SIGNUM) "???"
409#endif
410
411static void
412handle_signal(Event *event) {
413	debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
414	if (event->proc->state != STATE_IGNORED && !options.no_signals) {
415		output_line(event->proc, "--- %s (%s) ---",
416				shortsignal(event->proc, event->e_un.signum),
417				strsignal(event->e_un.signum));
418	}
419	continue_after_signal(event->proc->pid, event->e_un.signum);
420}
421
422static void
423handle_exit(Event *event) {
424	debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
425	if (event->proc->state != STATE_IGNORED) {
426		output_line(event->proc, "+++ exited (status %d) +++",
427				event->e_un.ret_val);
428	}
429	remove_process(event->proc);
430}
431
432static void
433handle_exit_signal(Event *event) {
434	debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
435	if (event->proc->state != STATE_IGNORED) {
436		output_line(event->proc, "+++ killed by %s +++",
437				shortsignal(event->proc, event->e_un.signum));
438	}
439	remove_process(event->proc);
440}
441
442static void
443output_syscall(struct process *proc, const char *name, enum tof tof,
444	       void (*output)(enum tof, struct process *,
445			      struct library_symbol *))
446{
447	static struct library syscall_lib;
448	if (syscall_lib.protolib == NULL) {
449		struct protolib *protolib
450			= protolib_cache_search(&g_protocache, "syscalls", 0, 1);
451		if (protolib == NULL) {
452			fprintf(stderr, "Couldn't load system call prototypes:"
453				" %s.\n", strerror(errno));
454
455			/* Instead, get a fake one just so we can
456			 * carry on, limping.  */
457			protolib = malloc(sizeof *protolib);
458			if (protolib == NULL) {
459				fprintf(stderr, "Couldn't even allocate a fake "
460					"prototype library: %s.\n",
461					strerror(errno));
462				abort();
463			}
464			protolib_init(protolib);
465		}
466
467		assert(protolib != NULL);
468		if (library_init(&syscall_lib, LT_LIBTYPE_SYSCALL) < 0) {
469			fprintf(stderr, "Couldn't initialize system call "
470				"library: %s.\n", strerror(errno));
471			abort();
472		}
473
474		library_set_soname(&syscall_lib, "SYS", 0);
475		syscall_lib.protolib = protolib;
476	}
477
478	struct library_symbol syscall;
479	if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) {
480		syscall.lib = &syscall_lib;
481		(*output)(tof, proc, &syscall);
482		library_symbol_destroy(&syscall);
483	}
484}
485
486static void
487output_syscall_left(struct process *proc, const char *name)
488{
489	output_syscall(proc, name, LT_TOF_SYSCALL, &output_left);
490}
491
492static void
493output_syscall_right(struct process *proc, const char *name)
494{
495	output_syscall(proc, name, LT_TOF_SYSCALLR, &output_right);
496}
497
498static void
499handle_syscall(Event *event) {
500	debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
501	if (event->proc->state != STATE_IGNORED) {
502		callstack_push_syscall(event->proc, event->e_un.sysnum);
503		if (options.syscalls)
504			output_syscall_left(event->proc,
505					    sysname(event->proc,
506						    event->e_un.sysnum));
507	}
508	continue_after_syscall(event->proc, event->e_un.sysnum, 0);
509}
510
511static void
512handle_exec(Event *event)
513{
514	struct process *proc = event->proc;
515
516	/* Save the PID so that we can use it after unsuccessful
517	 * process_exec.  */
518	pid_t pid = proc->pid;
519
520	debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid);
521	if (proc->state == STATE_IGNORED) {
522	untrace:
523		untrace_pid(pid);
524		remove_process(proc);
525		return;
526	}
527	output_line(proc, "--- Called exec() ---");
528
529	if (process_exec(proc) < 0) {
530		fprintf(stderr,
531			"couldn't reinitialize process %d after exec\n", pid);
532		goto untrace;
533	}
534
535	continue_after_exec(proc);
536}
537
538static void
539handle_arch_syscall(Event *event) {
540	debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
541	if (event->proc->state != STATE_IGNORED) {
542		callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
543		if (options.syscalls) {
544			output_syscall_left(event->proc,
545					    arch_sysname(event->proc,
546							 event->e_un.sysnum));
547		}
548	}
549	continue_process(event->proc->pid);
550}
551
552struct timeval current_time_spent;
553
554static void
555calc_time_spent(struct process *proc)
556{
557	struct timeval tv;
558	struct timezone tz;
559	struct timeval diff;
560	struct callstack_element *elem;
561
562	debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid);
563	elem = &proc->callstack[proc->callstack_depth - 1];
564
565	gettimeofday(&tv, &tz);
566
567	diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec;
568	if (tv.tv_usec >= elem->time_spent.tv_usec) {
569		diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec;
570	} else {
571		diff.tv_sec--;
572		diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
573	}
574	current_time_spent = diff;
575}
576
577static void
578handle_sysret(Event *event) {
579	debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
580	if (event->proc->state != STATE_IGNORED) {
581		if (opt_T || options.summary) {
582			calc_time_spent(event->proc);
583		}
584		if (options.syscalls)
585			output_syscall_right(event->proc,
586					     sysname(event->proc,
587						     event->e_un.sysnum));
588
589		assert(event->proc->callstack_depth > 0);
590		unsigned d = event->proc->callstack_depth - 1;
591		assert(event->proc->callstack[d].is_syscall);
592		callstack_pop(event->proc);
593	}
594	continue_after_syscall(event->proc, event->e_un.sysnum, 1);
595}
596
597static void
598handle_arch_sysret(Event *event) {
599	debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
600	if (event->proc->state != STATE_IGNORED) {
601		if (opt_T || options.summary) {
602			calc_time_spent(event->proc);
603		}
604		if (options.syscalls)
605			output_syscall_right(event->proc,
606					     arch_sysname(event->proc,
607							  event->e_un.sysnum));
608		callstack_pop(event->proc);
609	}
610	continue_process(event->proc->pid);
611}
612
613static void
614output_right_tos(struct process *proc)
615{
616	size_t d = proc->callstack_depth;
617	struct callstack_element *elem = &proc->callstack[d - 1];
618	if (proc->state != STATE_IGNORED)
619		output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc);
620}
621
622#ifndef ARCH_HAVE_SYMBOL_RET
623void arch_symbol_ret(struct process *proc, struct library_symbol *libsym)
624{
625}
626#endif
627
628static void
629handle_breakpoint(Event *event)
630{
631	int i, j;
632	struct breakpoint *sbp;
633	struct process *leader = event->proc->leader;
634	void *brk_addr = event->e_un.brk_addr;
635
636	/* The leader has terminated.  */
637	if (leader == NULL) {
638		continue_process(event->proc->pid);
639		return;
640	}
641
642	debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)",
643	      event->proc->pid, brk_addr);
644	debug(2, "event: breakpoint (%p)", brk_addr);
645
646	for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
647		if (brk_addr == event->proc->callstack[i].return_addr) {
648			for (j = event->proc->callstack_depth - 1; j > i; j--) {
649				callstack_pop(event->proc);
650			}
651			if (event->proc->state != STATE_IGNORED) {
652				if (opt_T || options.summary) {
653					calc_time_spent(event->proc);
654				}
655			}
656
657			struct library_symbol *libsym =
658			    event->proc->callstack[i].c_un.libfunc;
659
660			arch_symbol_ret(event->proc, libsym);
661			output_right_tos(event->proc);
662			callstack_pop(event->proc);
663
664			/* Pop also any other entries that seem like
665			 * they are linked to the current one: they
666			 * have the same return address, but were made
667			 * for different symbols.  This should only
668			 * happen for entry point tracing, i.e. for -x
669			 * everywhere, or -x and -e on MIPS.  */
670			while (event->proc->callstack_depth > 0) {
671				struct callstack_element *prev;
672				size_t d = event->proc->callstack_depth;
673				prev = &event->proc->callstack[d - 1];
674
675				if (prev->c_un.libfunc == libsym
676				    || prev->return_addr != brk_addr)
677					break;
678
679				arch_symbol_ret(event->proc,
680						prev->c_un.libfunc);
681				output_right_tos(event->proc);
682				callstack_pop(event->proc);
683			}
684
685			/* Maybe the previous callstack_pop's got rid
686			 * of the breakpoint, but if we are in a
687			 * recursive call, it's still enabled.  In
688			 * that case we need to skip it properly.  */
689			if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) {
690				continue_after_breakpoint(event->proc, sbp);
691			} else {
692				set_instruction_pointer(event->proc, brk_addr);
693				continue_process(event->proc->pid);
694			}
695			return;
696		}
697	}
698
699	if ((sbp = address2bpstruct(leader, brk_addr)) != NULL)
700		breakpoint_on_hit(sbp, event->proc);
701	else if (event->proc->state != STATE_IGNORED)
702		output_line(event->proc,
703			    "unexpected breakpoint at %p", brk_addr);
704
705	/* breakpoint_on_hit may delete its own breakpoint, so we have
706	 * to look it up again.  */
707	if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) {
708		if (event->proc->state != STATE_IGNORED
709		    && sbp->libsym != NULL) {
710			event->proc->stack_pointer = get_stack_pointer(event->proc);
711			callstack_push_symfunc(event->proc, sbp);
712			output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym);
713		}
714
715		breakpoint_on_continue(sbp, event->proc);
716		return;
717	} else {
718		set_instruction_pointer(event->proc, brk_addr);
719	}
720
721	continue_process(event->proc->pid);
722}
723
724static void
725callstack_push_syscall(struct process *proc, int sysnum)
726{
727	struct callstack_element *elem;
728
729	debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum);
730	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
731	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
732		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
733		abort();
734		return;
735	}
736
737	elem = &proc->callstack[proc->callstack_depth];
738	*elem = (struct callstack_element){};
739	elem->is_syscall = 1;
740	elem->c_un.syscall = sysnum;
741	elem->return_addr = NULL;
742
743	proc->callstack_depth++;
744	if (opt_T || options.summary) {
745		struct timezone tz;
746		gettimeofday(&elem->time_spent, &tz);
747	}
748}
749
750static void
751callstack_push_symfunc(struct process *proc, struct breakpoint *bp)
752{
753	struct callstack_element *elem;
754
755	debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)",
756	      proc->pid, bp->libsym->name);
757	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
758	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
759		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
760		abort();
761		return;
762	}
763
764	elem = &proc->callstack[proc->callstack_depth++];
765	*elem = (struct callstack_element){};
766	elem->is_syscall = 0;
767	elem->c_un.libfunc = bp->libsym;
768
769	struct breakpoint *rbp = NULL;
770	if (breakpoint_get_return_bp(&rbp, bp, proc) == 0) {
771		struct breakpoint *ext_rbp = insert_breakpoint(proc, rbp);
772		if (ext_rbp != rbp) {
773			breakpoint_destroy(rbp);
774			free(rbp);
775			rbp = ext_rbp;
776		}
777	}
778
779	elem->return_addr = rbp != NULL ? rbp->addr : 0;
780
781	if (opt_T || options.summary) {
782		struct timezone tz;
783		gettimeofday(&elem->time_spent, &tz);
784	}
785}
786
787void
788callstack_pop(struct process *proc)
789{
790	struct callstack_element *elem;
791	assert(proc->callstack_depth > 0);
792
793	debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid);
794	elem = &proc->callstack[proc->callstack_depth - 1];
795	if (!elem->is_syscall && elem->return_addr) {
796		struct breakpoint *bp
797			= address2bpstruct(proc->leader, elem->return_addr);
798		if (bp != NULL) {
799			breakpoint_on_hit(bp, proc);
800			delete_breakpoint(proc, bp);
801		}
802	}
803
804	if (elem->fetch_context != NULL)
805		fetch_arg_done(elem->fetch_context);
806
807	if (elem->arguments != NULL) {
808		val_dict_destroy(elem->arguments);
809		free(elem->arguments);
810	}
811
812	proc->callstack_depth--;
813}
814