handle_event.c revision e655ccffc4ba7bba317b01700f8fc50461d8c4dd
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); 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(Process *proc, int signum); 66static char * sysname(Process *proc, int sysnum); 67static char * arch_sysname(Process *proc, int sysnum); 68 69static Event * 70call_handler(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 Process * proc; 302 303 debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid); 304 305 proc = pid2proc(event->e_un.newpid); 306 if (!proc) { 307 pending_new_insert(event->e_un.newpid); 308 } else { 309 assert(proc->state == STATE_BEING_CREATED); 310 if (options.follow) { 311 proc->state = STATE_ATTACHED; 312 } else { 313 proc->state = STATE_IGNORED; 314 } 315 continue_process(proc->pid); 316 } 317} 318 319static char * 320shortsignal(Process *proc, int signum) { 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(Process *proc, int sysnum) { 345 static char result[128]; 346 static char *syscalent0[] = { 347#include "syscallent.h" 348 }; 349 static char *syscalent1[] = { 350#include "syscallent1.h" 351 }; 352 static char **syscalents[] = { syscalent0, syscalent1 }; 353 int nsyscals[] = { sizeof syscalent0 / sizeof syscalent0[0], 354 sizeof syscalent1 / sizeof syscalent1[0] 355 }; 356 357 debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 358 359 if (proc->personality > sizeof syscalents / sizeof syscalents[0]) 360 abort(); 361 if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) { 362 sprintf(result, "SYS_%d", sysnum); 363 return result; 364 } else { 365 sprintf(result, "SYS_%s", 366 syscalents[proc->personality][sysnum]); 367 return result; 368 } 369} 370 371static char * 372arch_sysname(Process *proc, int sysnum) { 373 static char result[128]; 374 static char *arch_syscalent[] = { 375#include "arch_syscallent.h" 376 }; 377 int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0]; 378 379 debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 380 381 if (sysnum < 0 || sysnum >= nsyscals) { 382 sprintf(result, "ARCH_%d", sysnum); 383 return result; 384 } else { 385 sprintf(result, "ARCH_%s", 386 arch_syscalent[sysnum]); 387 return result; 388 } 389} 390 391static void 392handle_signal(Event *event) { 393 debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 394 if (event->proc->state != STATE_IGNORED && !options.no_signals) { 395 output_line(event->proc, "--- %s (%s) ---", 396 shortsignal(event->proc, event->e_un.signum), 397 strsignal(event->e_un.signum)); 398 } 399 continue_after_signal(event->proc->pid, event->e_un.signum); 400} 401 402static void 403handle_exit(Event *event) { 404 debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val); 405 if (event->proc->state != STATE_IGNORED) { 406 output_line(event->proc, "+++ exited (status %d) +++", 407 event->e_un.ret_val); 408 } 409 remove_process(event->proc); 410} 411 412static void 413handle_exit_signal(Event *event) { 414 debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 415 if (event->proc->state != STATE_IGNORED) { 416 output_line(event->proc, "+++ killed by %s +++", 417 shortsignal(event->proc, event->e_un.signum)); 418 } 419 remove_process(event->proc); 420} 421 422static void 423output_syscall(struct Process *proc, const char *name, enum tof tof, 424 void (*output)(enum tof, struct Process *, 425 struct library_symbol *)) 426{ 427 struct library_symbol syscall; 428 if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) { 429 (*output)(tof, proc, &syscall); 430 library_symbol_destroy(&syscall); 431 } 432} 433 434static void 435output_syscall_left(struct Process *proc, const char *name) 436{ 437 output_syscall(proc, name, LT_TOF_SYSCALL, &output_left); 438} 439 440static void 441output_syscall_right(struct Process *proc, const char *name) 442{ 443 output_syscall(proc, name, LT_TOF_SYSCALLR, &output_right); 444} 445 446static void 447handle_syscall(Event *event) { 448 debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 449 if (event->proc->state != STATE_IGNORED) { 450 callstack_push_syscall(event->proc, event->e_un.sysnum); 451 if (options.syscalls) 452 output_syscall_left(event->proc, 453 sysname(event->proc, 454 event->e_un.sysnum)); 455 } 456 continue_after_syscall(event->proc, event->e_un.sysnum, 0); 457} 458 459static void 460handle_exec(Event * event) { 461 Process * proc = event->proc; 462 463 /* Save the PID so that we can use it after unsuccessful 464 * process_exec. */ 465 pid_t pid = proc->pid; 466 467 debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid); 468 if (proc->state == STATE_IGNORED) { 469 untrace: 470 untrace_pid(pid); 471 remove_process(proc); 472 return; 473 } 474 output_line(proc, "--- Called exec() ---"); 475 476 if (process_exec(proc) < 0) { 477 fprintf(stderr, 478 "couldn't reinitialize process %d after exec\n", pid); 479 goto untrace; 480 } 481 482 continue_process(proc->pid); 483 484 /* After the exec, we expect to hit the first executable 485 * instruction. 486 * 487 * XXX TODO It would be nice to have this removed, but then we 488 * need to do that also for initial call to wait_for_proc in 489 * execute_program. In that case we could generate a 490 * EVENT_FIRST event or something, or maybe this could somehow 491 * be rolled into EVENT_NEW. */ 492 wait_for_proc(proc->pid); 493 continue_process(proc->pid); 494} 495 496static void 497handle_arch_syscall(Event *event) { 498 debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 499 if (event->proc->state != STATE_IGNORED) { 500 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); 501 if (options.syscalls) { 502 output_syscall_left(event->proc, 503 arch_sysname(event->proc, 504 event->e_un.sysnum)); 505 } 506 } 507 continue_process(event->proc->pid); 508} 509 510struct timeval current_time_spent; 511 512static void 513calc_time_spent(Process *proc) { 514 struct timeval tv; 515 struct timezone tz; 516 struct timeval diff; 517 struct callstack_element *elem; 518 519 debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid); 520 elem = &proc->callstack[proc->callstack_depth - 1]; 521 522 gettimeofday(&tv, &tz); 523 524 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec; 525 if (tv.tv_usec >= elem->time_spent.tv_usec) { 526 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec; 527 } else { 528 diff.tv_sec--; 529 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec; 530 } 531 current_time_spent = diff; 532} 533 534static void 535handle_sysret(Event *event) { 536 debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 537 if (event->proc->state != STATE_IGNORED) { 538 if (opt_T || options.summary) { 539 calc_time_spent(event->proc); 540 } 541 if (options.syscalls) 542 output_syscall_right(event->proc, 543 sysname(event->proc, 544 event->e_un.sysnum)); 545 546 assert(event->proc->callstack_depth > 0); 547 unsigned d = event->proc->callstack_depth - 1; 548 assert(event->proc->callstack[d].is_syscall); 549 callstack_pop(event->proc); 550 } 551 continue_after_syscall(event->proc, event->e_un.sysnum, 1); 552} 553 554static void 555handle_arch_sysret(Event *event) { 556 debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 557 if (event->proc->state != STATE_IGNORED) { 558 if (opt_T || options.summary) { 559 calc_time_spent(event->proc); 560 } 561 if (options.syscalls) 562 output_syscall_right(event->proc, 563 arch_sysname(event->proc, 564 event->e_un.sysnum)); 565 callstack_pop(event->proc); 566 } 567 continue_process(event->proc->pid); 568} 569 570static void 571output_right_tos(struct Process *proc) 572{ 573 size_t d = proc->callstack_depth; 574 struct callstack_element *elem = &proc->callstack[d - 1]; 575 if (proc->state != STATE_IGNORED) 576 output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc); 577} 578 579#ifndef ARCH_HAVE_SYMBOL_RET 580void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym) 581{ 582} 583#endif 584 585static void 586handle_breakpoint(Event *event) 587{ 588 int i, j; 589 struct breakpoint *sbp; 590 Process *leader = event->proc->leader; 591 void *brk_addr = event->e_un.brk_addr; 592 593 /* The leader has terminated. */ 594 if (leader == NULL) { 595 continue_process(event->proc->pid); 596 return; 597 } 598 599 debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", 600 event->proc->pid, brk_addr); 601 debug(2, "event: breakpoint (%p)", brk_addr); 602 603 for (i = event->proc->callstack_depth - 1; i >= 0; i--) { 604 if (brk_addr == event->proc->callstack[i].return_addr) { 605 for (j = event->proc->callstack_depth - 1; j > i; j--) { 606 callstack_pop(event->proc); 607 } 608 if (event->proc->state != STATE_IGNORED) { 609 if (opt_T || options.summary) { 610 calc_time_spent(event->proc); 611 } 612 } 613 event->proc->return_addr = brk_addr; 614 615 struct library_symbol *libsym = 616 event->proc->callstack[i].c_un.libfunc; 617 618 arch_symbol_ret(event->proc, libsym); 619 output_right_tos(event->proc); 620 callstack_pop(event->proc); 621 622 /* Pop also any other entries that seem like 623 * they are linked to the current one: they 624 * have the same return address, but were made 625 * for different symbols. This should only 626 * happen for entry point tracing, i.e. for -x 627 * everywhere, or -x and -e on MIPS. */ 628 while (event->proc->callstack_depth > 0) { 629 struct callstack_element *prev; 630 size_t d = event->proc->callstack_depth; 631 prev = &event->proc->callstack[d - 1]; 632 633 if (prev->c_un.libfunc == libsym 634 || prev->return_addr != brk_addr) 635 break; 636 637 arch_symbol_ret(event->proc, 638 prev->c_un.libfunc); 639 output_right_tos(event->proc); 640 callstack_pop(event->proc); 641 } 642 643 /* Maybe the previous callstack_pop's got rid 644 * of the breakpoint, but if we are in a 645 * recursive call, it's still enabled. In 646 * that case we need to skip it properly. */ 647 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) { 648 continue_after_breakpoint(event->proc, sbp); 649 } else { 650 set_instruction_pointer(event->proc, brk_addr); 651 continue_process(event->proc->pid); 652 } 653 return; 654 } 655 } 656 657 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) 658 breakpoint_on_hit(sbp, event->proc); 659 else if (event->proc->state != STATE_IGNORED) 660 output_line(event->proc, 661 "unexpected breakpoint at %p", brk_addr); 662 663 /* breakpoint_on_hit may delete its own breakpoint, so we have 664 * to look it up again. */ 665 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) { 666 if (event->proc->state != STATE_IGNORED 667 && sbp->libsym != NULL) { 668 event->proc->stack_pointer = get_stack_pointer(event->proc); 669 event->proc->return_addr = 670 get_return_addr(event->proc, event->proc->stack_pointer); 671 callstack_push_symfunc(event->proc, sbp->libsym); 672 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym); 673 } 674 675 breakpoint_on_continue(sbp, event->proc); 676 return; 677 } else { 678 set_instruction_pointer(event->proc, brk_addr); 679 } 680 681 continue_process(event->proc->pid); 682} 683 684static void 685callstack_push_syscall(Process *proc, int sysnum) { 686 struct callstack_element *elem; 687 688 debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum); 689 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 690 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 691 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 692 abort(); 693 return; 694 } 695 696 elem = &proc->callstack[proc->callstack_depth]; 697 *elem = (struct callstack_element){}; 698 elem->is_syscall = 1; 699 elem->c_un.syscall = sysnum; 700 elem->return_addr = NULL; 701 702 proc->callstack_depth++; 703 if (opt_T || options.summary) { 704 struct timezone tz; 705 gettimeofday(&elem->time_spent, &tz); 706 } 707} 708 709static void 710callstack_push_symfunc(Process *proc, struct library_symbol *sym) { 711 struct callstack_element *elem; 712 713 debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name); 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 = (struct callstack_element){}; 723 elem->is_syscall = 0; 724 elem->c_un.libfunc = sym; 725 726 elem->return_addr = proc->return_addr; 727 if (elem->return_addr) 728 insert_breakpoint(proc, elem->return_addr, NULL); 729 730 if (opt_T || options.summary) { 731 struct timezone tz; 732 gettimeofday(&elem->time_spent, &tz); 733 } 734} 735 736void 737callstack_pop(struct Process *proc) 738{ 739 struct callstack_element *elem; 740 assert(proc->callstack_depth > 0); 741 742 debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid); 743 elem = &proc->callstack[proc->callstack_depth - 1]; 744 if (!elem->is_syscall && elem->return_addr) 745 delete_breakpoint(proc, elem->return_addr); 746 747 if (elem->fetch_context != NULL) 748 fetch_arg_done(elem->fetch_context); 749 750 if (elem->arguments != NULL) { 751 val_dict_destroy(elem->arguments); 752 free(elem->arguments); 753 } 754 755 proc->callstack_depth--; 756} 757