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