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