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