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