handle_event.c revision 8e682c2763991227c1492cb17aa0744eb04bc0a0
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	Pending_New *p, *pred;
255
256	debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid);
257
258	p = pending_news;
259	pred = NULL;
260	if (p->pid == pid) {
261		pending_news = p->next;
262		free(p);
263	} else {
264		while (p) {
265			if (p->pid == pid) {
266				pred->next = p->next;
267				free(p);
268			}
269			pred = p;
270			p = p->next;
271		}
272	}
273}
274
275static void
276handle_clone(Event *event)
277{
278	debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid);
279
280	struct process *proc = malloc(sizeof(*proc));
281	pid_t newpid = event->e_un.newpid;
282	if (proc == NULL
283	    || process_clone(proc, event->proc, newpid) < 0) {
284		free(proc);
285		proc = NULL;
286		fprintf(stderr,
287			"Couldn't initialize tracing of process %d.\n",
288			newpid);
289
290	} else {
291		proc->parent = event->proc;
292		/* We save register values to the arch pointer, and
293		 * these need to be per-thread.  XXX arch_ptr should
294		 * be retired in favor of fetch interface anyway.  */
295		proc->arch_ptr = NULL;
296	}
297
298	if (pending_new(newpid)) {
299		pending_new_remove(newpid);
300
301		if (proc != NULL) {
302			proc->event_handler = NULL;
303			if (event->proc->state == STATE_ATTACHED
304			    && options.follow)
305				proc->state = STATE_ATTACHED;
306			else
307				proc->state = STATE_IGNORED;
308		}
309
310		continue_process(newpid);
311
312	} else if (proc != NULL) {
313		proc->state = STATE_BEING_CREATED;
314	}
315
316	if (event->type != EVENT_VFORK)
317		continue_process(event->proc->pid);
318	else if (proc != NULL)
319		continue_after_vfork(proc);
320	else
321		continue_process(newpid);
322}
323
324static void
325handle_new(Event *event)
326{
327	debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid);
328
329	struct process *proc = pid2proc(event->e_un.newpid);
330	if (!proc) {
331		pending_new_insert(event->e_un.newpid);
332	} else {
333		assert(proc->state == STATE_BEING_CREATED);
334		if (options.follow) {
335			proc->state = STATE_ATTACHED;
336		} else {
337			proc->state = STATE_IGNORED;
338		}
339		continue_process(proc->pid);
340	}
341}
342
343static char *
344shortsignal(struct process *proc, int signum)
345{
346	static char *signalent0[] = {
347#include "signalent.h"
348	};
349	static char *signalent1[] = {
350#include "signalent1.h"
351	};
352	static char **signalents[] = { signalent0, signalent1 };
353	int nsignals[] = { sizeof signalent0 / sizeof signalent0[0],
354		sizeof signalent1 / sizeof signalent1[0]
355	};
356
357	debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum);
358
359	assert(proc->personality < sizeof signalents / sizeof signalents[0]);
360	if (signum < 0 || signum >= nsignals[proc->personality]) {
361		return "UNKNOWN_SIGNAL";
362	} else {
363		return signalents[proc->personality][signum];
364	}
365}
366
367static char *
368sysname(struct process *proc, int sysnum)
369{
370	static char result[128];
371	static char *syscallent0[] = {
372#include "syscallent.h"
373	};
374	static char *syscallent1[] = {
375#include "syscallent1.h"
376	};
377	static char **syscallents[] = { syscallent0, syscallent1 };
378	int nsyscalls[] = {
379		sizeof syscallent0 / sizeof syscallent0[0],
380		sizeof syscallent1 / sizeof syscallent1[0],
381	};
382
383	debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
384
385	assert(proc->personality < sizeof syscallents / sizeof syscallents[0]);
386	if (sysnum < 0 || sysnum >= nsyscalls[proc->personality]) {
387		sprintf(result, "SYS_%d", sysnum);
388		return result;
389	} else {
390		sprintf(result, "SYS_%s",
391			syscallents[proc->personality][sysnum]);
392		return result;
393	}
394}
395
396static char *
397arch_sysname(struct process *proc, int sysnum)
398{
399	static char result[128];
400	static char *arch_syscallent[] = {
401#include "arch_syscallent.h"
402	};
403	int nsyscalls = sizeof arch_syscallent / sizeof arch_syscallent[0];
404
405	debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
406
407	if (sysnum < 0 || sysnum >= nsyscalls) {
408		sprintf(result, "ARCH_%d", sysnum);
409		return result;
410	} else {
411		sprintf(result, "ARCH_%s", arch_syscallent[sysnum]);
412		return result;
413	}
414}
415
416#ifndef HAVE_STRSIGNAL
417# define strsignal(SIGNUM) "???"
418#endif
419
420static void
421handle_signal(Event *event) {
422	debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
423	if (event->proc->state != STATE_IGNORED && !options.no_signals) {
424		output_line(event->proc, "--- %s (%s) ---",
425				shortsignal(event->proc, event->e_un.signum),
426				strsignal(event->e_un.signum));
427	}
428	continue_after_signal(event->proc->pid, event->e_un.signum);
429}
430
431static void
432handle_exit(Event *event) {
433	debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
434	if (event->proc->state != STATE_IGNORED) {
435		output_line(event->proc, "+++ exited (status %d) +++",
436				event->e_un.ret_val);
437	}
438	remove_process(event->proc);
439}
440
441static void
442handle_exit_signal(Event *event) {
443	debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
444	if (event->proc->state != STATE_IGNORED) {
445		output_line(event->proc, "+++ killed by %s +++",
446				shortsignal(event->proc, event->e_un.signum));
447	}
448	remove_process(event->proc);
449}
450
451static void
452output_syscall(struct process *proc, const char *name, enum tof tof,
453	       void (*output)(enum tof, struct process *,
454			      struct library_symbol *))
455{
456	struct library_symbol syscall;
457	if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) {
458		(*output)(tof, proc, &syscall);
459		library_symbol_destroy(&syscall);
460	}
461}
462
463static void
464output_syscall_left(struct process *proc, const char *name)
465{
466	output_syscall(proc, name, LT_TOF_SYSCALL, &output_left);
467}
468
469static void
470output_syscall_right(struct process *proc, const char *name)
471{
472	output_syscall(proc, name, LT_TOF_SYSCALLR, &output_right);
473}
474
475static void
476handle_syscall(Event *event) {
477	debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
478	if (event->proc->state != STATE_IGNORED) {
479		callstack_push_syscall(event->proc, event->e_un.sysnum);
480		if (options.syscalls)
481			output_syscall_left(event->proc,
482					    sysname(event->proc,
483						    event->e_un.sysnum));
484	}
485	continue_after_syscall(event->proc, event->e_un.sysnum, 0);
486}
487
488static void
489handle_exec(Event *event)
490{
491	struct process *proc = event->proc;
492
493	/* Save the PID so that we can use it after unsuccessful
494	 * process_exec.  */
495	pid_t pid = proc->pid;
496
497	debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid);
498	if (proc->state == STATE_IGNORED) {
499	untrace:
500		untrace_pid(pid);
501		remove_process(proc);
502		return;
503	}
504	output_line(proc, "--- Called exec() ---");
505
506	if (process_exec(proc) < 0) {
507		fprintf(stderr,
508			"couldn't reinitialize process %d after exec\n", pid);
509		goto untrace;
510	}
511
512	continue_after_exec(proc);
513}
514
515static void
516handle_arch_syscall(Event *event) {
517	debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
518	if (event->proc->state != STATE_IGNORED) {
519		callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
520		if (options.syscalls) {
521			output_syscall_left(event->proc,
522					    arch_sysname(event->proc,
523							 event->e_un.sysnum));
524		}
525	}
526	continue_process(event->proc->pid);
527}
528
529struct timeval current_time_spent;
530
531static void
532calc_time_spent(struct process *proc)
533{
534	struct timeval tv;
535	struct timezone tz;
536	struct timeval diff;
537	struct callstack_element *elem;
538
539	debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid);
540	elem = &proc->callstack[proc->callstack_depth - 1];
541
542	gettimeofday(&tv, &tz);
543
544	diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec;
545	if (tv.tv_usec >= elem->time_spent.tv_usec) {
546		diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec;
547	} else {
548		diff.tv_sec--;
549		diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
550	}
551	current_time_spent = diff;
552}
553
554static void
555handle_sysret(Event *event) {
556	debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
557	if (event->proc->state != STATE_IGNORED) {
558		if (opt_T || options.summary) {
559			calc_time_spent(event->proc);
560		}
561		if (options.syscalls)
562			output_syscall_right(event->proc,
563					     sysname(event->proc,
564						     event->e_un.sysnum));
565
566		assert(event->proc->callstack_depth > 0);
567		unsigned d = event->proc->callstack_depth - 1;
568		assert(event->proc->callstack[d].is_syscall);
569		callstack_pop(event->proc);
570	}
571	continue_after_syscall(event->proc, event->e_un.sysnum, 1);
572}
573
574static void
575handle_arch_sysret(Event *event) {
576	debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
577	if (event->proc->state != STATE_IGNORED) {
578		if (opt_T || options.summary) {
579			calc_time_spent(event->proc);
580		}
581		if (options.syscalls)
582			output_syscall_right(event->proc,
583					     arch_sysname(event->proc,
584							  event->e_un.sysnum));
585		callstack_pop(event->proc);
586	}
587	continue_process(event->proc->pid);
588}
589
590static void
591output_right_tos(struct process *proc)
592{
593	size_t d = proc->callstack_depth;
594	struct callstack_element *elem = &proc->callstack[d - 1];
595	if (proc->state != STATE_IGNORED)
596		output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc);
597}
598
599#ifndef ARCH_HAVE_SYMBOL_RET
600void arch_symbol_ret(struct process *proc, struct library_symbol *libsym)
601{
602}
603#endif
604
605static void
606handle_breakpoint(Event *event)
607{
608	int i, j;
609	struct breakpoint *sbp;
610	struct process *leader = event->proc->leader;
611	void *brk_addr = event->e_un.brk_addr;
612
613	/* The leader has terminated.  */
614	if (leader == NULL) {
615		continue_process(event->proc->pid);
616		return;
617	}
618
619	debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)",
620	      event->proc->pid, brk_addr);
621	debug(2, "event: breakpoint (%p)", brk_addr);
622
623	for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
624		if (brk_addr == event->proc->callstack[i].return_addr) {
625			for (j = event->proc->callstack_depth - 1; j > i; j--) {
626				callstack_pop(event->proc);
627			}
628			if (event->proc->state != STATE_IGNORED) {
629				if (opt_T || options.summary) {
630					calc_time_spent(event->proc);
631				}
632			}
633			event->proc->return_addr = brk_addr;
634
635			struct library_symbol *libsym =
636			    event->proc->callstack[i].c_un.libfunc;
637
638			arch_symbol_ret(event->proc, libsym);
639			output_right_tos(event->proc);
640			callstack_pop(event->proc);
641
642			/* Pop also any other entries that seem like
643			 * they are linked to the current one: they
644			 * have the same return address, but were made
645			 * for different symbols.  This should only
646			 * happen for entry point tracing, i.e. for -x
647			 * everywhere, or -x and -e on MIPS.  */
648			while (event->proc->callstack_depth > 0) {
649				struct callstack_element *prev;
650				size_t d = event->proc->callstack_depth;
651				prev = &event->proc->callstack[d - 1];
652
653				if (prev->c_un.libfunc == libsym
654				    || prev->return_addr != brk_addr)
655					break;
656
657				arch_symbol_ret(event->proc,
658						prev->c_un.libfunc);
659				output_right_tos(event->proc);
660				callstack_pop(event->proc);
661			}
662
663			/* Maybe the previous callstack_pop's got rid
664			 * of the breakpoint, but if we are in a
665			 * recursive call, it's still enabled.  In
666			 * that case we need to skip it properly.  */
667			if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) {
668				continue_after_breakpoint(event->proc, sbp);
669			} else {
670				set_instruction_pointer(event->proc, brk_addr);
671				continue_process(event->proc->pid);
672			}
673			return;
674		}
675	}
676
677	if ((sbp = address2bpstruct(leader, brk_addr)) != NULL)
678		breakpoint_on_hit(sbp, event->proc);
679	else if (event->proc->state != STATE_IGNORED)
680		output_line(event->proc,
681			    "unexpected breakpoint at %p", brk_addr);
682
683	/* breakpoint_on_hit may delete its own breakpoint, so we have
684	 * to look it up again.  */
685	if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) {
686		if (event->proc->state != STATE_IGNORED
687		    && sbp->libsym != NULL) {
688			event->proc->stack_pointer = get_stack_pointer(event->proc);
689			event->proc->return_addr =
690				get_return_addr(event->proc, event->proc->stack_pointer);
691			callstack_push_symfunc(event->proc, sbp->libsym);
692			output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym);
693		}
694
695		breakpoint_on_continue(sbp, event->proc);
696		return;
697	} else {
698		set_instruction_pointer(event->proc, brk_addr);
699	}
700
701	continue_process(event->proc->pid);
702}
703
704static void
705callstack_push_syscall(struct process *proc, int sysnum)
706{
707	struct callstack_element *elem;
708
709	debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum);
710	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
711	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
712		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
713		abort();
714		return;
715	}
716
717	elem = &proc->callstack[proc->callstack_depth];
718	*elem = (struct callstack_element){};
719	elem->is_syscall = 1;
720	elem->c_un.syscall = sysnum;
721	elem->return_addr = NULL;
722
723	proc->callstack_depth++;
724	if (opt_T || options.summary) {
725		struct timezone tz;
726		gettimeofday(&elem->time_spent, &tz);
727	}
728}
729
730static void
731callstack_push_symfunc(struct process *proc, struct library_symbol *sym)
732{
733	struct callstack_element *elem;
734
735	debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name);
736	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
737	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
738		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
739		abort();
740		return;
741	}
742
743	elem = &proc->callstack[proc->callstack_depth++];
744	*elem = (struct callstack_element){};
745	elem->is_syscall = 0;
746	elem->c_un.libfunc = sym;
747
748	elem->return_addr = proc->return_addr;
749	if (elem->return_addr)
750		insert_breakpoint(proc, elem->return_addr, NULL);
751
752	if (opt_T || options.summary) {
753		struct timezone tz;
754		gettimeofday(&elem->time_spent, &tz);
755	}
756}
757
758void
759callstack_pop(struct process *proc)
760{
761	struct callstack_element *elem;
762	assert(proc->callstack_depth > 0);
763
764	debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid);
765	elem = &proc->callstack[proc->callstack_depth - 1];
766	if (!elem->is_syscall && elem->return_addr)
767		delete_breakpoint(proc, elem->return_addr);
768
769	if (elem->fetch_context != NULL)
770		fetch_arg_done(elem->fetch_context);
771
772	if (elem->arguments != NULL) {
773		val_dict_destroy(elem->arguments);
774		free(elem->arguments);
775	}
776
777	proc->callstack_depth--;
778}
779