handle_event.c revision 1429874dee5758cc99c0dae73bd3f928109e53d7
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
18static void handle_signal(Event *event);
19static void handle_exit(Event *event);
20static void handle_exit_signal(Event *event);
21static void handle_syscall(Event *event);
22static void handle_arch_syscall(Event *event);
23static void handle_sysret(Event *event);
24static void handle_arch_sysret(Event *event);
25static void handle_clone(Event *event);
26static void handle_exec(Event *event);
27static void handle_breakpoint(Event *event);
28static void handle_new(Event *event);
29
30static void callstack_push_syscall(Process *proc, int sysnum);
31static void callstack_push_symfunc(Process *proc,
32				   struct library_symbol *sym);
33static void callstack_pop(Process *proc);
34
35static char * shortsignal(Process *proc, int signum);
36static char * sysname(Process *proc, int sysnum);
37static char * arch_sysname(Process *proc, int sysnum);
38
39static Event *
40call_handler(Process * proc, Event * event)
41{
42	assert(proc != NULL);
43
44	Event_Handler * handler = proc->event_handler;
45	if (handler == NULL)
46		return event;
47
48	return (*handler->on_event) (handler, event);
49}
50
51void
52handle_event(Event *event)
53{
54	if (exiting == 1) {
55		debug(1, "ltrace about to exit");
56		os_ltrace_exiting();
57		exiting = 2;
58	}
59	debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
60	      event->proc ? event->proc->pid : -1, event->type);
61
62	/* If the thread group or an individual task define an
63	   overriding event handler, give them a chance to kick in.
64	   We will end up calling both handlers, if the first one
65	   doesn't sink the event.  */
66	if (event->proc != NULL) {
67		event = call_handler(event->proc, event);
68		if (event == NULL)
69			/* It was handled.  */
70			return;
71
72		/* Note: the previous handler has a chance to alter
73		 * the event.  */
74		if (event->proc != NULL
75		    && event->proc->leader != NULL
76		    && event->proc != event->proc->leader) {
77			event = call_handler(event->proc->leader, event);
78			if (event == NULL)
79				return;
80		}
81	}
82
83	switch (event->type) {
84	case EVENT_NONE:
85		debug(1, "event: none");
86		return;
87	case EVENT_SIGNAL:
88		debug(1, "event: signal (%s [%d])",
89		      shortsignal(event->proc, event->e_un.signum),
90		      event->e_un.signum);
91		handle_signal(event);
92		return;
93	case EVENT_EXIT:
94		debug(1, "event: exit (%d)", event->e_un.ret_val);
95		handle_exit(event);
96		return;
97	case EVENT_EXIT_SIGNAL:
98		debug(1, "event: exit signal (%s [%d])",
99		      shortsignal(event->proc, event->e_un.signum),
100		      event->e_un.signum);
101		handle_exit_signal(event);
102		return;
103	case EVENT_SYSCALL:
104		debug(1, "event: syscall (%s [%d])",
105		      sysname(event->proc, event->e_un.sysnum),
106		      event->e_un.sysnum);
107		handle_syscall(event);
108		return;
109	case EVENT_SYSRET:
110		debug(1, "event: sysret (%s [%d])",
111		      sysname(event->proc, event->e_un.sysnum),
112		      event->e_un.sysnum);
113		handle_sysret(event);
114		return;
115	case EVENT_ARCH_SYSCALL:
116		debug(1, "event: arch_syscall (%s [%d])",
117				arch_sysname(event->proc, event->e_un.sysnum),
118				event->e_un.sysnum);
119		handle_arch_syscall(event);
120		return;
121	case EVENT_ARCH_SYSRET:
122		debug(1, "event: arch_sysret (%s [%d])",
123				arch_sysname(event->proc, event->e_un.sysnum),
124				event->e_un.sysnum);
125		handle_arch_sysret(event);
126		return;
127	case EVENT_CLONE:
128	case EVENT_VFORK:
129		debug(1, "event: clone (%u)", event->e_un.newpid);
130		handle_clone(event);
131		return;
132	case EVENT_EXEC:
133		debug(1, "event: exec()");
134		handle_exec(event);
135		return;
136	case EVENT_BREAKPOINT:
137		debug(1, "event: breakpoint");
138		handle_breakpoint(event);
139		return;
140	case EVENT_NEW:
141		debug(1, "event: new process");
142		handle_new(event);
143		return;
144	default:
145		fprintf(stderr, "Error! unknown event?\n");
146		exit(1);
147	}
148}
149
150/* TODO */
151static void *
152address_clone(void * addr, void * data)
153{
154	debug(DEBUG_FUNCTION, "address_clone(%p)", addr);
155	return addr;
156}
157
158static void *
159breakpoint_clone(void *bp, void *data)
160{
161	Breakpoint * b;
162	Dict *map = data;
163	debug(DEBUG_FUNCTION, "breakpoint_clone(%p)", bp);
164	b = malloc(sizeof(Breakpoint));
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		if (event->proc->breakpoints_enabled == 0) {
457			enable_all_breakpoints(event->proc);
458		}
459	}
460	continue_after_syscall(event->proc, event->e_un.sysnum, 0);
461}
462
463static void
464handle_exec(Event * event) {
465	Process * proc = event->proc;
466	pid_t saved_pid;
467
468	debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid);
469	if (proc->state == STATE_IGNORED) {
470		untrace_pid(proc->pid);
471		remove_process(proc);
472		return;
473	}
474	output_line(proc, "--- Called exec() ---");
475	proc->mask_32bit = 0;
476	proc->personality = 0;
477	proc->arch_ptr = NULL;
478	free(proc->filename);
479	proc->filename = pid2name(proc->pid);
480	saved_pid = proc->pid;
481	proc->pid = 0;
482	breakpoints_init(proc, 0);
483	proc->pid = saved_pid;
484	proc->callstack_depth = 0;
485	continue_process(proc->pid);
486}
487
488static void
489handle_arch_syscall(Event *event) {
490	debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
491	if (event->proc->state != STATE_IGNORED) {
492		callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
493		if (options.syscalls) {
494			output_left(LT_TOF_SYSCALL, event->proc,
495					arch_sysname(event->proc, event->e_un.sysnum));
496		}
497		if (event->proc->breakpoints_enabled == 0) {
498			enable_all_breakpoints(event->proc);
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_right(LT_TOF_SYSCALLR, event->proc,
537					sysname(event->proc, event->e_un.sysnum));
538		}
539		assert(event->proc->callstack_depth > 0);
540		unsigned d = event->proc->callstack_depth - 1;
541		assert(event->proc->callstack[d].is_syscall);
542		callstack_pop(event->proc);
543	}
544	continue_after_syscall(event->proc, event->e_un.sysnum, 1);
545}
546
547static void
548handle_arch_sysret(Event *event) {
549	debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
550	if (event->proc->state != STATE_IGNORED) {
551		if (opt_T || options.summary) {
552			calc_time_spent(event->proc);
553		}
554		if (options.syscalls) {
555			output_right(LT_TOF_SYSCALLR, event->proc,
556					arch_sysname(event->proc, event->e_un.sysnum));
557		}
558		callstack_pop(event->proc);
559	}
560	continue_process(event->proc->pid);
561}
562
563#ifdef __powerpc__
564void *get_count_register (Process *proc);
565#endif
566
567static void
568output_right_tos(struct Process *proc)
569{
570	size_t d = proc->callstack_depth;
571	struct callstack_element *elem = &proc->callstack[d - 1];
572	if (proc->state != STATE_IGNORED)
573		output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc->name);
574}
575
576static void
577handle_breakpoint(Event *event)
578{
579	int i, j;
580	Breakpoint *sbp;
581	Process *leader = event->proc->leader;
582	void *brk_addr = event->e_un.brk_addr;
583
584	/* The leader has terminated.  */
585	if (leader == NULL) {
586		continue_process(event->proc->pid);
587		return;
588	}
589
590	debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)",
591	      event->proc->pid, brk_addr);
592	debug(2, "event: breakpoint (%p)", brk_addr);
593
594#ifdef __powerpc__
595	/* Need to skip following NOP's to prevent a fake function from being stacked.  */
596	long stub_addr = (long) get_count_register(event->proc);
597	Breakpoint *stub_bp = NULL;
598	char nop_instruction[] = PPC_NOP;
599
600	stub_bp = address2bpstruct(leader, brk_addr);
601
602	if (stub_bp) {
603		unsigned char *bp_instruction = stub_bp->orig_value;
604
605		if (memcmp(bp_instruction, nop_instruction,
606			    PPC_NOP_LENGTH) == 0) {
607			if (stub_addr != (long) brk_addr) {
608				set_instruction_pointer(event->proc,
609							brk_addr + 4);
610				continue_process(event->proc->pid);
611				return;
612			}
613		}
614	}
615#endif
616
617	for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
618		if (brk_addr == event->proc->callstack[i].return_addr) {
619#ifdef __powerpc__
620			/*
621			 * PPC HACK! (XXX FIXME TODO)
622			 * The PLT gets modified during the first call,
623			 * so be sure to re-enable the breakpoint.
624			 */
625			unsigned long a;
626			struct library_symbol *libsym =
627			    event->proc->callstack[i].c_un.libfunc;
628			void *addr = sym2addr(event->proc, libsym);
629
630			if (libsym->plt_type != LS_TOPLT_POINT) {
631				unsigned char break_insn[] = BREAKPOINT_VALUE;
632
633				sbp = address2bpstruct(leader, addr);
634				assert(sbp);
635				a = ptrace(PTRACE_PEEKTEXT, event->proc->pid,
636					   addr);
637
638				if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) {
639					sbp->enabled--;
640					insert_breakpoint(event->proc, addr,
641							  libsym, 1);
642				}
643			} else {
644				sbp = dict_find_entry(leader->breakpoints, addr);
645				/* On powerpc, the breakpoint address
646				   may end up being actual entry point
647				   of the library symbol, not the PLT
648				   address we computed.  In that case,
649				   sbp is NULL.  */
650				if (sbp == NULL || addr != sbp->addr) {
651					insert_breakpoint(event->proc, addr,
652							  libsym, 1);
653				}
654			}
655#elif defined(__mips__)
656			void *addr = NULL;
657			struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
658			struct library_symbol *new_sym;
659			assert(sym);
660			addr = sym2addr(event->proc, sym);
661			sbp = dict_find_entry(leader->breakpoints, addr);
662			if (sbp) {
663				if (addr != sbp->addr) {
664					insert_breakpoint(event->proc, addr, sym, 1);
665				}
666			} else {
667				new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
668				memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
669				new_sym->next = leader->list_of_symbols;
670				leader->list_of_symbols = new_sym;
671				insert_breakpoint(event->proc, addr, new_sym, 1);
672			}
673#endif
674			for (j = event->proc->callstack_depth - 1; j > i; j--) {
675				callstack_pop(event->proc);
676			}
677			if (event->proc->state != STATE_IGNORED) {
678				if (opt_T || options.summary) {
679					calc_time_spent(event->proc);
680				}
681			}
682			event->proc->return_addr = brk_addr;
683
684			output_right_tos(event->proc);
685			callstack_pop(event->proc);
686
687			/* Pop also any other entries that seem like
688			 * they are linked to the current one: they
689			 * have the same return address, but were made
690			 * for different symbols.  This should only
691			 * happen for entry point tracing, i.e. for -x
692			 * everywhere, or -x and -e on PPC64.  */
693			while (event->proc->callstack_depth > 0) {
694				struct callstack_element *prev;
695				size_t d = event->proc->callstack_depth;
696				prev = &event->proc->callstack[d - 1];
697
698				if (prev->c_un.libfunc == libsym
699				    || prev->return_addr != brk_addr)
700					break;
701
702				output_right_tos(event->proc);
703				callstack_pop(event->proc);
704			}
705
706			sbp = address2bpstruct(leader, brk_addr);
707			continue_after_breakpoint(event->proc, sbp);
708			return;
709		}
710	}
711
712	if ((sbp = address2bpstruct(leader, brk_addr))) {
713		if (sbp->libsym == NULL) {
714			continue_after_breakpoint(event->proc, sbp);
715			return;
716		}
717
718		if (strcmp(sbp->libsym->name, "") == 0) {
719			debug(DEBUG_PROCESS, "Hit _dl_debug_state breakpoint!\n");
720			arch_check_dbg(leader);
721		}
722
723		if (event->proc->state != STATE_IGNORED) {
724			event->proc->stack_pointer = get_stack_pointer(event->proc);
725			event->proc->return_addr =
726				get_return_addr(event->proc, event->proc->stack_pointer);
727			callstack_push_symfunc(event->proc, sbp->libsym);
728			output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name);
729		}
730#ifdef PLT_REINITALISATION_BP
731		if (event->proc->need_to_reinitialize_breakpoints
732		    && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) ==
733			0))
734			reinitialize_breakpoints(leader);
735#endif
736
737		continue_after_breakpoint(event->proc, sbp);
738		return;
739	}
740
741	if (event->proc->state != STATE_IGNORED && !options.no_plt) {
742		output_line(event->proc, "unexpected breakpoint at %p",
743			    brk_addr);
744	}
745	continue_process(event->proc->pid);
746}
747
748static void
749callstack_push_syscall(Process *proc, int sysnum) {
750	struct callstack_element *elem;
751
752	debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum);
753	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
754	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
755		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
756		abort();
757		return;
758	}
759
760	elem = &proc->callstack[proc->callstack_depth];
761	elem->is_syscall = 1;
762	elem->c_un.syscall = sysnum;
763	elem->return_addr = NULL;
764
765	proc->callstack_depth++;
766	if (opt_T || options.summary) {
767		struct timezone tz;
768		gettimeofday(&elem->time_spent, &tz);
769	}
770}
771
772static void
773callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
774	struct callstack_element *elem;
775
776	debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name);
777	/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
778	if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
779		fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
780		abort();
781		return;
782	}
783
784	elem = &proc->callstack[proc->callstack_depth++];
785	elem->is_syscall = 0;
786	elem->c_un.libfunc = sym;
787
788	elem->return_addr = proc->return_addr;
789	if (elem->return_addr) {
790		insert_breakpoint(proc, elem->return_addr, NULL, 1);
791	}
792
793	/* handle functions like atexit() on mips which have no return */
794	if (opt_T || options.summary) {
795		struct timezone tz;
796		gettimeofday(&elem->time_spent, &tz);
797	}
798}
799
800static void
801callstack_pop(Process *proc) {
802	struct callstack_element *elem;
803	assert(proc->callstack_depth > 0);
804
805	debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid);
806	elem = &proc->callstack[proc->callstack_depth - 1];
807	if (!elem->is_syscall && elem->return_addr) {
808		assert(proc->leader != NULL);
809		delete_breakpoint(proc, elem->return_addr);
810	}
811	if (elem->arch_ptr != NULL) {
812		free(elem->arch_ptr);
813		elem->arch_ptr = NULL;
814	}
815	proc->callstack_depth--;
816}
817