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