handle_event.c revision 5165cf30236ab00b4b38b67794e8055f1076f619
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 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(Process *proc, int sysnum); 58static void callstack_push_symfunc(Process *proc, 59 struct library_symbol *sym); 60static void callstack_pop(Process *proc); 61 62static char * shortsignal(Process *proc, int signum); 63static char * sysname(Process *proc, int sysnum); 64static char * arch_sysname(Process *proc, int sysnum); 65 66static Event * 67call_handler(Process * proc, Event * event) 68{ 69 assert(proc != NULL); 70 71 struct event_handler *handler = proc->event_handler; 72 if (handler == NULL) 73 return event; 74 75 return (*handler->on_event) (handler, event); 76} 77 78void 79handle_event(Event *event) 80{ 81 if (exiting == 1) { 82 debug(1, "ltrace about to exit"); 83 os_ltrace_exiting(); 84 exiting = 2; 85 } 86 debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)", 87 event->proc ? event->proc->pid : -1, event->type); 88 89 /* If the thread group or an individual task define an 90 overriding event handler, give them a chance to kick in. 91 We will end up calling both handlers, if the first one 92 doesn't sink the event. */ 93 if (event->proc != NULL) { 94 event = call_handler(event->proc, event); 95 if (event == NULL) 96 /* It was handled. */ 97 return; 98 99 /* Note: the previous handler has a chance to alter 100 * the event. */ 101 if (event->proc != NULL 102 && event->proc->leader != NULL 103 && event->proc != event->proc->leader) { 104 event = call_handler(event->proc->leader, event); 105 if (event == NULL) 106 return; 107 } 108 } 109 110 switch (event->type) { 111 case EVENT_NONE: 112 debug(1, "event: none"); 113 return; 114 case EVENT_SIGNAL: 115 debug(1, "[%d] event: signal (%s [%d])", 116 event->proc->pid, 117 shortsignal(event->proc, event->e_un.signum), 118 event->e_un.signum); 119 handle_signal(event); 120 return; 121 case EVENT_EXIT: 122 debug(1, "[%d] event: exit (%d)", 123 event->proc->pid, 124 event->e_un.ret_val); 125 handle_exit(event); 126 return; 127 case EVENT_EXIT_SIGNAL: 128 debug(1, "[%d] event: exit signal (%s [%d])", 129 event->proc->pid, 130 shortsignal(event->proc, event->e_un.signum), 131 event->e_un.signum); 132 handle_exit_signal(event); 133 return; 134 case EVENT_SYSCALL: 135 debug(1, "[%d] event: syscall (%s [%d])", 136 event->proc->pid, 137 sysname(event->proc, event->e_un.sysnum), 138 event->e_un.sysnum); 139 handle_syscall(event); 140 return; 141 case EVENT_SYSRET: 142 debug(1, "[%d] event: sysret (%s [%d])", 143 event->proc->pid, 144 sysname(event->proc, event->e_un.sysnum), 145 event->e_un.sysnum); 146 handle_sysret(event); 147 return; 148 case EVENT_ARCH_SYSCALL: 149 debug(1, "[%d] event: arch_syscall (%s [%d])", 150 event->proc->pid, 151 arch_sysname(event->proc, event->e_un.sysnum), 152 event->e_un.sysnum); 153 handle_arch_syscall(event); 154 return; 155 case EVENT_ARCH_SYSRET: 156 debug(1, "[%d] event: arch_sysret (%s [%d])", 157 event->proc->pid, 158 arch_sysname(event->proc, event->e_un.sysnum), 159 event->e_un.sysnum); 160 handle_arch_sysret(event); 161 return; 162 case EVENT_CLONE: 163 case EVENT_VFORK: 164 debug(1, "[%d] event: clone (%u)", 165 event->proc->pid, event->e_un.newpid); 166 handle_clone(event); 167 return; 168 case EVENT_EXEC: 169 debug(1, "[%d] event: exec()", 170 event->proc->pid); 171 handle_exec(event); 172 return; 173 case EVENT_BREAKPOINT: 174 debug(1, "[%d] event: breakpoint %p", 175 event->proc->pid, event->e_un.brk_addr); 176 handle_breakpoint(event); 177 return; 178 case EVENT_NEW: 179 debug(1, "[%d] event: new process", 180 event->e_un.newpid); 181 handle_new(event); 182 return; 183 default: 184 fprintf(stderr, "Error! unknown event?\n"); 185 exit(1); 186 } 187} 188 189typedef struct Pending_New Pending_New; 190struct Pending_New { 191 pid_t pid; 192 Pending_New * next; 193}; 194static Pending_New * pending_news = NULL; 195 196static int 197pending_new(pid_t pid) { 198 Pending_New * p; 199 200 debug(DEBUG_FUNCTION, "pending_new(%d)", pid); 201 202 p = pending_news; 203 while (p) { 204 if (p->pid == pid) { 205 return 1; 206 } 207 p = p->next; 208 } 209 return 0; 210} 211 212static void 213pending_new_insert(pid_t pid) { 214 Pending_New * p; 215 216 debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid); 217 218 p = malloc(sizeof(Pending_New)); 219 if (!p) { 220 perror("malloc()"); 221 exit(1); 222 } 223 p->pid = pid; 224 p->next = pending_news; 225 pending_news = p; 226} 227 228static void 229pending_new_remove(pid_t pid) { 230 Pending_New *p, *pred; 231 232 debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid); 233 234 p = pending_news; 235 pred = NULL; 236 if (p->pid == pid) { 237 pending_news = p->next; 238 free(p); 239 } else { 240 while (p) { 241 if (p->pid == pid) { 242 pred->next = p->next; 243 free(p); 244 } 245 pred = p; 246 p = p->next; 247 } 248 } 249} 250 251static void 252handle_clone(Event *event) 253{ 254 debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid); 255 256 struct Process *proc = malloc(sizeof(*proc)); 257 if (proc == NULL) { 258 fail: 259 free(proc); 260 fprintf(stderr, 261 "Error during init of tracing process %d\n" 262 "This process won't be traced.\n", 263 event->proc->pid); 264 return; 265 } 266 267 if (process_clone(proc, event->proc, event->e_un.newpid) < 0) 268 goto fail; 269 proc->parent = event->proc; 270 271 /* We save register values to the arch pointer, and these need 272 to be per-thread. */ 273 proc->arch_ptr = NULL; 274 275 if (pending_new(proc->pid)) { 276 pending_new_remove(proc->pid); 277 /* XXX this used to be destroy_event_handler call, but 278 * I don't think we want to call that on a shared 279 * state. */ 280 proc->event_handler = NULL; 281 if (event->proc->state == STATE_ATTACHED && options.follow) 282 proc->state = STATE_ATTACHED; 283 else 284 proc->state = STATE_IGNORED; 285 continue_process(proc->pid); 286 } else { 287 proc->state = STATE_BEING_CREATED; 288 } 289 290 if (event->type == EVENT_VFORK) 291 continue_after_vfork(proc); 292 else 293 continue_process(event->proc->pid); 294} 295 296static void 297handle_new(Event * event) { 298 Process * proc; 299 300 debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid); 301 302 proc = pid2proc(event->e_un.newpid); 303 if (!proc) { 304 pending_new_insert(event->e_un.newpid); 305 } else { 306 assert(proc->state == STATE_BEING_CREATED); 307 if (options.follow) { 308 proc->state = STATE_ATTACHED; 309 } else { 310 proc->state = STATE_IGNORED; 311 } 312 continue_process(proc->pid); 313 } 314} 315 316static char * 317shortsignal(Process *proc, int signum) { 318 static char *signalent0[] = { 319#include "signalent.h" 320 }; 321 static char *signalent1[] = { 322#include "signalent1.h" 323 }; 324 static char **signalents[] = { signalent0, signalent1 }; 325 int nsignals[] = { sizeof signalent0 / sizeof signalent0[0], 326 sizeof signalent1 / sizeof signalent1[0] 327 }; 328 329 debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum); 330 331 if (proc->personality > sizeof signalents / sizeof signalents[0]) 332 abort(); 333 if (signum < 0 || signum >= nsignals[proc->personality]) { 334 return "UNKNOWN_SIGNAL"; 335 } else { 336 return signalents[proc->personality][signum]; 337 } 338} 339 340static char * 341sysname(Process *proc, int sysnum) { 342 static char result[128]; 343 static char *syscalent0[] = { 344#include "syscallent.h" 345 }; 346 static char *syscalent1[] = { 347#include "syscallent1.h" 348 }; 349 static char **syscalents[] = { syscalent0, syscalent1 }; 350 int nsyscals[] = { sizeof syscalent0 / sizeof syscalent0[0], 351 sizeof syscalent1 / sizeof syscalent1[0] 352 }; 353 354 debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 355 356 if (proc->personality > sizeof syscalents / sizeof syscalents[0]) 357 abort(); 358 if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) { 359 sprintf(result, "SYS_%d", sysnum); 360 return result; 361 } else { 362 sprintf(result, "SYS_%s", 363 syscalents[proc->personality][sysnum]); 364 return result; 365 } 366} 367 368static char * 369arch_sysname(Process *proc, int sysnum) { 370 static char result[128]; 371 static char *arch_syscalent[] = { 372#include "arch_syscallent.h" 373 }; 374 int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0]; 375 376 debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 377 378 if (sysnum < 0 || sysnum >= nsyscals) { 379 sprintf(result, "ARCH_%d", sysnum); 380 return result; 381 } else { 382 sprintf(result, "ARCH_%s", 383 arch_syscalent[sysnum]); 384 return result; 385 } 386} 387 388static void 389handle_signal(Event *event) { 390 debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 391 if (event->proc->state != STATE_IGNORED && !options.no_signals) { 392 output_line(event->proc, "--- %s (%s) ---", 393 shortsignal(event->proc, event->e_un.signum), 394 strsignal(event->e_un.signum)); 395 } 396 continue_after_signal(event->proc->pid, event->e_un.signum); 397} 398 399static void 400handle_exit(Event *event) { 401 debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val); 402 if (event->proc->state != STATE_IGNORED) { 403 output_line(event->proc, "+++ exited (status %d) +++", 404 event->e_un.ret_val); 405 } 406 remove_process(event->proc); 407} 408 409static void 410handle_exit_signal(Event *event) { 411 debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 412 if (event->proc->state != STATE_IGNORED) { 413 output_line(event->proc, "+++ killed by %s +++", 414 shortsignal(event->proc, event->e_un.signum)); 415 } 416 remove_process(event->proc); 417} 418 419static void 420output_syscall(struct Process *proc, const char *name, enum tof tof, 421 void (*output)(enum tof, struct Process *, 422 struct library_symbol *)) 423{ 424 struct library_symbol syscall; 425 if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) { 426 (*output)(tof, proc, &syscall); 427 library_symbol_destroy(&syscall); 428 } 429} 430 431static void 432output_syscall_left(struct Process *proc, const char *name) 433{ 434 output_syscall(proc, name, LT_TOF_SYSCALL, &output_left); 435} 436 437static void 438output_syscall_right(struct Process *proc, const char *name) 439{ 440 output_syscall(proc, name, LT_TOF_SYSCALLR, &output_right); 441} 442 443static void 444handle_syscall(Event *event) { 445 debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 446 if (event->proc->state != STATE_IGNORED) { 447 callstack_push_syscall(event->proc, event->e_un.sysnum); 448 if (options.syscalls) 449 output_syscall_left(event->proc, 450 sysname(event->proc, 451 event->e_un.sysnum)); 452 } 453 continue_after_syscall(event->proc, event->e_un.sysnum, 0); 454} 455 456static void 457handle_exec(Event * event) { 458 Process * proc = event->proc; 459 460 /* Save the PID so that we can use it after unsuccessful 461 * process_exec. */ 462 pid_t pid = proc->pid; 463 464 debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid); 465 if (proc->state == STATE_IGNORED) { 466 untrace: 467 untrace_pid(pid); 468 remove_process(proc); 469 return; 470 } 471 output_line(proc, "--- Called exec() ---"); 472 473 if (process_exec(proc) < 0) { 474 fprintf(stderr, 475 "couldn't reinitialize process %d after exec\n", pid); 476 goto untrace; 477 } 478 479 continue_process(proc->pid); 480 481 /* After the exec, we expect to hit the first executable 482 * instruction. 483 * 484 * XXX TODO It would be nice to have this removed, but then we 485 * need to do that also for initial call to wait_for_proc in 486 * execute_program. In that case we could generate a 487 * EVENT_FIRST event or something, or maybe this could somehow 488 * be rolled into EVENT_NEW. */ 489 wait_for_proc(proc->pid); 490 continue_process(proc->pid); 491} 492 493static void 494handle_arch_syscall(Event *event) { 495 debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 496 if (event->proc->state != STATE_IGNORED) { 497 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); 498 if (options.syscalls) { 499 output_syscall_left(event->proc, 500 arch_sysname(event->proc, 501 event->e_un.sysnum)); 502 } 503 } 504 continue_process(event->proc->pid); 505} 506 507struct timeval current_time_spent; 508 509static void 510calc_time_spent(Process *proc) { 511 struct timeval tv; 512 struct timezone tz; 513 struct timeval diff; 514 struct callstack_element *elem; 515 516 debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid); 517 elem = &proc->callstack[proc->callstack_depth - 1]; 518 519 gettimeofday(&tv, &tz); 520 521 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec; 522 if (tv.tv_usec >= elem->time_spent.tv_usec) { 523 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec; 524 } else { 525 diff.tv_sec++; 526 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec; 527 } 528 current_time_spent = diff; 529} 530 531static void 532handle_sysret(Event *event) { 533 debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 534 if (event->proc->state != STATE_IGNORED) { 535 if (opt_T || options.summary) { 536 calc_time_spent(event->proc); 537 } 538 if (options.syscalls) 539 output_syscall_right(event->proc, 540 sysname(event->proc, 541 event->e_un.sysnum)); 542 543 assert(event->proc->callstack_depth > 0); 544 unsigned d = event->proc->callstack_depth - 1; 545 assert(event->proc->callstack[d].is_syscall); 546 callstack_pop(event->proc); 547 } 548 continue_after_syscall(event->proc, event->e_un.sysnum, 1); 549} 550 551static void 552handle_arch_sysret(Event *event) { 553 debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 554 if (event->proc->state != STATE_IGNORED) { 555 if (opt_T || options.summary) { 556 calc_time_spent(event->proc); 557 } 558 if (options.syscalls) 559 output_syscall_right(event->proc, 560 arch_sysname(event->proc, 561 event->e_un.sysnum)); 562 callstack_pop(event->proc); 563 } 564 continue_process(event->proc->pid); 565} 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); 574} 575 576static void 577handle_breakpoint(Event *event) 578{ 579 int i, j; 580 struct 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 for (i = event->proc->callstack_depth - 1; i >= 0; i--) { 595 if (brk_addr == event->proc->callstack[i].return_addr) { 596 for (j = event->proc->callstack_depth - 1; j > i; j--) { 597 callstack_pop(event->proc); 598 } 599 if (event->proc->state != STATE_IGNORED) { 600 if (opt_T || options.summary) { 601 calc_time_spent(event->proc); 602 } 603 } 604 event->proc->return_addr = brk_addr; 605 606 struct library_symbol *libsym = 607 event->proc->callstack[i].c_un.libfunc; 608 609 output_right_tos(event->proc); 610 callstack_pop(event->proc); 611 612 /* Pop also any other entries that seem like 613 * they are linked to the current one: they 614 * have the same return address, but were made 615 * for different symbols. This should only 616 * happen for entry point tracing, i.e. for -x 617 * everywhere, or -x and -e on PPC64. */ 618 while (event->proc->callstack_depth > 0) { 619 struct callstack_element *prev; 620 size_t d = event->proc->callstack_depth; 621 prev = &event->proc->callstack[d - 1]; 622 623 if (prev->c_un.libfunc == libsym 624 || prev->return_addr != brk_addr) 625 break; 626 627 output_right_tos(event->proc); 628 callstack_pop(event->proc); 629 } 630 631 /* Maybe the previous callstack_pop's got rid 632 * of the breakpoint, but if we are in a 633 * recursive call, it's still enabled. In 634 * that case we need to skip it properly. */ 635 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) { 636 continue_after_breakpoint(event->proc, sbp); 637 } else { 638 set_instruction_pointer(event->proc, brk_addr); 639 continue_process(event->proc->pid); 640 } 641 return; 642 } 643 } 644 645 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) 646 breakpoint_on_hit(sbp, event->proc); 647 else if (event->proc->state != STATE_IGNORED) 648 output_line(event->proc, 649 "unexpected breakpoint at %p", brk_addr); 650 651 /* breakpoint_on_hit may delete its own breakpoint, so we have 652 * to look it up again. */ 653 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) { 654 if (event->proc->state != STATE_IGNORED 655 && sbp->libsym != NULL) { 656 event->proc->stack_pointer = get_stack_pointer(event->proc); 657 event->proc->return_addr = 658 get_return_addr(event->proc, event->proc->stack_pointer); 659 callstack_push_symfunc(event->proc, sbp->libsym); 660 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym); 661 } 662 663 breakpoint_on_continue(sbp, event->proc); 664 return; 665 } else { 666 set_instruction_pointer(event->proc, brk_addr); 667 } 668 669 continue_process(event->proc->pid); 670} 671 672static void 673callstack_push_syscall(Process *proc, int sysnum) { 674 struct callstack_element *elem; 675 676 debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum); 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 elem = &proc->callstack[proc->callstack_depth]; 685 *elem = (struct callstack_element){}; 686 elem->is_syscall = 1; 687 elem->c_un.syscall = sysnum; 688 elem->return_addr = NULL; 689 690 proc->callstack_depth++; 691 if (opt_T || options.summary) { 692 struct timezone tz; 693 gettimeofday(&elem->time_spent, &tz); 694 } 695} 696 697static void 698callstack_push_symfunc(Process *proc, struct library_symbol *sym) { 699 struct callstack_element *elem; 700 701 debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name); 702 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 703 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 704 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 705 abort(); 706 return; 707 } 708 709 elem = &proc->callstack[proc->callstack_depth++]; 710 *elem = (struct callstack_element){}; 711 elem->is_syscall = 0; 712 elem->c_un.libfunc = sym; 713 714 elem->return_addr = proc->return_addr; 715 if (elem->return_addr) 716 insert_breakpoint(proc, elem->return_addr, NULL); 717 718 if (opt_T || options.summary) { 719 struct timezone tz; 720 gettimeofday(&elem->time_spent, &tz); 721 } 722} 723 724static void 725callstack_pop(Process *proc) { 726 struct callstack_element *elem; 727 assert(proc->callstack_depth > 0); 728 729 debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid); 730 elem = &proc->callstack[proc->callstack_depth - 1]; 731 if (!elem->is_syscall && elem->return_addr) { 732 assert(proc->leader != NULL); 733 delete_breakpoint(proc, elem->return_addr); 734 } 735 proc->callstack_depth--; 736} 737