handle_event.c revision f9d93c50bd246ea7fd42e0c8ad24aa01467e76ac
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 118 case EVENT_SIGNAL: 119 assert(event->proc != NULL); 120 debug(1, "[%d] event: signal (%s [%d])", 121 event->proc->pid, 122 shortsignal(event->proc, event->e_un.signum), 123 event->e_un.signum); 124 handle_signal(event); 125 return; 126 127 case EVENT_EXIT: 128 assert(event->proc != NULL); 129 debug(1, "[%d] event: exit (%d)", 130 event->proc->pid, 131 event->e_un.ret_val); 132 handle_exit(event); 133 return; 134 135 case EVENT_EXIT_SIGNAL: 136 assert(event->proc != NULL); 137 debug(1, "[%d] event: exit signal (%s [%d])", 138 event->proc->pid, 139 shortsignal(event->proc, event->e_un.signum), 140 event->e_un.signum); 141 handle_exit_signal(event); 142 return; 143 144 case EVENT_SYSCALL: 145 assert(event->proc != NULL); 146 debug(1, "[%d] event: syscall (%s [%d])", 147 event->proc->pid, 148 sysname(event->proc, event->e_un.sysnum), 149 event->e_un.sysnum); 150 handle_syscall(event); 151 return; 152 153 case EVENT_SYSRET: 154 assert(event->proc != NULL); 155 debug(1, "[%d] event: sysret (%s [%d])", 156 event->proc->pid, 157 sysname(event->proc, event->e_un.sysnum), 158 event->e_un.sysnum); 159 handle_sysret(event); 160 return; 161 162 case EVENT_ARCH_SYSCALL: 163 assert(event->proc != NULL); 164 debug(1, "[%d] event: arch_syscall (%s [%d])", 165 event->proc->pid, 166 arch_sysname(event->proc, event->e_un.sysnum), 167 event->e_un.sysnum); 168 handle_arch_syscall(event); 169 return; 170 171 case EVENT_ARCH_SYSRET: 172 assert(event->proc != NULL); 173 debug(1, "[%d] event: arch_sysret (%s [%d])", 174 event->proc->pid, 175 arch_sysname(event->proc, event->e_un.sysnum), 176 event->e_un.sysnum); 177 handle_arch_sysret(event); 178 return; 179 180 case EVENT_CLONE: 181 case EVENT_VFORK: 182 assert(event->proc != NULL); 183 debug(1, "[%d] event: clone (%u)", 184 event->proc->pid, event->e_un.newpid); 185 handle_clone(event); 186 return; 187 188 case EVENT_EXEC: 189 assert(event->proc != NULL); 190 debug(1, "[%d] event: exec()", 191 event->proc->pid); 192 handle_exec(event); 193 return; 194 195 case EVENT_BREAKPOINT: 196 assert(event->proc != NULL); 197 debug(1, "[%d] event: breakpoint %p", 198 event->proc->pid, event->e_un.brk_addr); 199 handle_breakpoint(event); 200 return; 201 202 case EVENT_NEW: 203 debug(1, "[%d] event: new process", 204 event->e_un.newpid); 205 handle_new(event); 206 return; 207 default: 208 fprintf(stderr, "Error! unknown event?\n"); 209 exit(1); 210 } 211} 212 213typedef struct Pending_New Pending_New; 214struct Pending_New { 215 pid_t pid; 216 Pending_New * next; 217}; 218static Pending_New * pending_news = NULL; 219 220static int 221pending_new(pid_t pid) { 222 Pending_New * p; 223 224 debug(DEBUG_FUNCTION, "pending_new(%d)", pid); 225 226 p = pending_news; 227 while (p) { 228 if (p->pid == pid) { 229 return 1; 230 } 231 p = p->next; 232 } 233 return 0; 234} 235 236static void 237pending_new_insert(pid_t pid) { 238 Pending_New * p; 239 240 debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid); 241 242 p = malloc(sizeof(Pending_New)); 243 if (!p) { 244 perror("malloc()"); 245 exit(1); 246 } 247 p->pid = pid; 248 p->next = pending_news; 249 pending_news = p; 250} 251 252static void 253pending_new_remove(pid_t pid) 254{ 255 debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid); 256 257 Pending_New **pp; 258 for (pp = &pending_news; *pp != NULL; pp = &(*pp)->next) 259 if ((*pp)->pid == pid) { 260 Pending_New *p = *pp; 261 *pp = p->next; 262 free(p); 263 return; 264 } 265} 266 267static void 268handle_clone(Event *event) 269{ 270 debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid); 271 272 struct process *proc = malloc(sizeof(*proc)); 273 pid_t newpid = event->e_un.newpid; 274 if (proc == NULL 275 || process_clone(proc, event->proc, newpid) < 0) { 276 free(proc); 277 proc = NULL; 278 fprintf(stderr, 279 "Couldn't initialize tracing of process %d.\n", 280 newpid); 281 282 } else { 283 proc->parent = event->proc; 284 /* We save register values to the arch pointer, and 285 * these need to be per-thread. XXX arch_ptr should 286 * be retired in favor of fetch interface anyway. */ 287 proc->arch_ptr = NULL; 288 } 289 290 if (pending_new(newpid)) { 291 pending_new_remove(newpid); 292 293 if (proc != NULL) { 294 proc->event_handler = NULL; 295 if (event->proc->state == STATE_ATTACHED 296 && options.follow) 297 proc->state = STATE_ATTACHED; 298 else 299 proc->state = STATE_IGNORED; 300 } 301 302 continue_process(newpid); 303 304 } else if (proc != NULL) { 305 proc->state = STATE_BEING_CREATED; 306 } 307 308 if (event->type != EVENT_VFORK) 309 continue_process(event->proc->pid); 310 else if (proc != NULL) 311 continue_after_vfork(proc); 312 else 313 continue_process(newpid); 314} 315 316static void 317handle_new(Event *event) 318{ 319 debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid); 320 321 struct process *proc = pid2proc(event->e_un.newpid); 322 if (!proc) { 323 pending_new_insert(event->e_un.newpid); 324 } else { 325 assert(proc->state == STATE_BEING_CREATED); 326 if (options.follow) { 327 proc->state = STATE_ATTACHED; 328 } else { 329 proc->state = STATE_IGNORED; 330 } 331 continue_process(proc->pid); 332 } 333} 334 335static char * 336shortsignal(struct process *proc, int signum) 337{ 338 static char *signalent0[] = { 339#include "signalent.h" 340 }; 341 static char *signalent1[] = { 342#include "signalent1.h" 343 }; 344 static char **signalents[] = { signalent0, signalent1 }; 345 int nsignals[] = { sizeof signalent0 / sizeof signalent0[0], 346 sizeof signalent1 / sizeof signalent1[0] 347 }; 348 349 debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum); 350 351 assert(proc->personality < sizeof signalents / sizeof signalents[0]); 352 if (signum < 0 || signum >= nsignals[proc->personality]) { 353 return "UNKNOWN_SIGNAL"; 354 } else { 355 return signalents[proc->personality][signum]; 356 } 357} 358 359static char * 360sysname(struct process *proc, int sysnum) 361{ 362 static char result[128]; 363 static char *syscallent0[] = { 364#include "syscallent.h" 365 }; 366 static char *syscallent1[] = { 367#include "syscallent1.h" 368 }; 369 static char **syscallents[] = { syscallent0, syscallent1 }; 370 int nsyscalls[] = { 371 sizeof syscallent0 / sizeof syscallent0[0], 372 sizeof syscallent1 / sizeof syscallent1[0], 373 }; 374 375 debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 376 377 assert(proc->personality < sizeof syscallents / sizeof syscallents[0]); 378 if (sysnum < 0 || sysnum >= nsyscalls[proc->personality]) { 379 sprintf(result, "SYS_%d", sysnum); 380 return result; 381 } else { 382 sprintf(result, "SYS_%s", 383 syscallents[proc->personality][sysnum]); 384 return result; 385 } 386} 387 388static char * 389arch_sysname(struct process *proc, int sysnum) 390{ 391 static char result[128]; 392 static char *arch_syscallent[] = { 393#include "arch_syscallent.h" 394 }; 395 int nsyscalls = sizeof arch_syscallent / sizeof arch_syscallent[0]; 396 397 debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 398 399 if (sysnum < 0 || sysnum >= nsyscalls) { 400 sprintf(result, "ARCH_%d", sysnum); 401 return result; 402 } else { 403 sprintf(result, "ARCH_%s", arch_syscallent[sysnum]); 404 return result; 405 } 406} 407 408#ifndef HAVE_STRSIGNAL 409# define strsignal(SIGNUM) "???" 410#endif 411 412static void 413handle_signal(Event *event) { 414 debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 415 if (event->proc->state != STATE_IGNORED && !options.no_signals) { 416 output_line(event->proc, "--- %s (%s) ---", 417 shortsignal(event->proc, event->e_un.signum), 418 strsignal(event->e_un.signum)); 419 } 420 continue_after_signal(event->proc->pid, event->e_un.signum); 421} 422 423static void 424handle_exit(Event *event) { 425 debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val); 426 if (event->proc->state != STATE_IGNORED) { 427 output_line(event->proc, "+++ exited (status %d) +++", 428 event->e_un.ret_val); 429 } 430 remove_process(event->proc); 431} 432 433static void 434handle_exit_signal(Event *event) { 435 debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 436 if (event->proc->state != STATE_IGNORED) { 437 output_line(event->proc, "+++ killed by %s +++", 438 shortsignal(event->proc, event->e_un.signum)); 439 } 440 remove_process(event->proc); 441} 442 443static void 444output_syscall(struct process *proc, const char *name, enum tof tof, 445 void (*output)(enum tof, struct process *, 446 struct library_symbol *)) 447{ 448 struct library_symbol syscall; 449 if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) { 450 (*output)(tof, proc, &syscall); 451 library_symbol_destroy(&syscall); 452 } 453} 454 455static void 456output_syscall_left(struct process *proc, const char *name) 457{ 458 output_syscall(proc, name, LT_TOF_SYSCALL, &output_left); 459} 460 461static void 462output_syscall_right(struct process *proc, const char *name) 463{ 464 output_syscall(proc, name, LT_TOF_SYSCALLR, &output_right); 465} 466 467static void 468handle_syscall(Event *event) { 469 debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 470 if (event->proc->state != STATE_IGNORED) { 471 callstack_push_syscall(event->proc, event->e_un.sysnum); 472 if (options.syscalls) 473 output_syscall_left(event->proc, 474 sysname(event->proc, 475 event->e_un.sysnum)); 476 } 477 continue_after_syscall(event->proc, event->e_un.sysnum, 0); 478} 479 480static void 481handle_exec(Event *event) 482{ 483 struct process *proc = event->proc; 484 485 /* Save the PID so that we can use it after unsuccessful 486 * process_exec. */ 487 pid_t pid = proc->pid; 488 489 debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid); 490 if (proc->state == STATE_IGNORED) { 491 untrace: 492 untrace_pid(pid); 493 remove_process(proc); 494 return; 495 } 496 output_line(proc, "--- Called exec() ---"); 497 498 if (process_exec(proc) < 0) { 499 fprintf(stderr, 500 "couldn't reinitialize process %d after exec\n", pid); 501 goto untrace; 502 } 503 504 continue_after_exec(proc); 505} 506 507static void 508handle_arch_syscall(Event *event) { 509 debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 510 if (event->proc->state != STATE_IGNORED) { 511 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); 512 if (options.syscalls) { 513 output_syscall_left(event->proc, 514 arch_sysname(event->proc, 515 event->e_un.sysnum)); 516 } 517 } 518 continue_process(event->proc->pid); 519} 520 521struct timeval current_time_spent; 522 523static void 524calc_time_spent(struct process *proc) 525{ 526 struct timeval tv; 527 struct timezone tz; 528 struct timeval diff; 529 struct callstack_element *elem; 530 531 debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid); 532 elem = &proc->callstack[proc->callstack_depth - 1]; 533 534 gettimeofday(&tv, &tz); 535 536 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec; 537 if (tv.tv_usec >= elem->time_spent.tv_usec) { 538 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec; 539 } else { 540 diff.tv_sec--; 541 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec; 542 } 543 current_time_spent = diff; 544} 545 546static void 547handle_sysret(Event *event) { 548 debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 549 if (event->proc->state != STATE_IGNORED) { 550 if (opt_T || options.summary) { 551 calc_time_spent(event->proc); 552 } 553 if (options.syscalls) 554 output_syscall_right(event->proc, 555 sysname(event->proc, 556 event->e_un.sysnum)); 557 558 assert(event->proc->callstack_depth > 0); 559 unsigned d = event->proc->callstack_depth - 1; 560 assert(event->proc->callstack[d].is_syscall); 561 callstack_pop(event->proc); 562 } 563 continue_after_syscall(event->proc, event->e_un.sysnum, 1); 564} 565 566static void 567handle_arch_sysret(Event *event) { 568 debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 569 if (event->proc->state != STATE_IGNORED) { 570 if (opt_T || options.summary) { 571 calc_time_spent(event->proc); 572 } 573 if (options.syscalls) 574 output_syscall_right(event->proc, 575 arch_sysname(event->proc, 576 event->e_un.sysnum)); 577 callstack_pop(event->proc); 578 } 579 continue_process(event->proc->pid); 580} 581 582static void 583output_right_tos(struct process *proc) 584{ 585 size_t d = proc->callstack_depth; 586 struct callstack_element *elem = &proc->callstack[d - 1]; 587 if (proc->state != STATE_IGNORED) 588 output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc); 589} 590 591#ifndef ARCH_HAVE_SYMBOL_RET 592void arch_symbol_ret(struct process *proc, struct library_symbol *libsym) 593{ 594} 595#endif 596 597static void 598handle_breakpoint(Event *event) 599{ 600 int i, j; 601 struct breakpoint *sbp; 602 struct process *leader = event->proc->leader; 603 void *brk_addr = event->e_un.brk_addr; 604 605 /* The leader has terminated. */ 606 if (leader == NULL) { 607 continue_process(event->proc->pid); 608 return; 609 } 610 611 debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", 612 event->proc->pid, brk_addr); 613 debug(2, "event: breakpoint (%p)", brk_addr); 614 615 for (i = event->proc->callstack_depth - 1; i >= 0; i--) { 616 if (brk_addr == event->proc->callstack[i].return_addr) { 617 for (j = event->proc->callstack_depth - 1; j > i; j--) { 618 callstack_pop(event->proc); 619 } 620 if (event->proc->state != STATE_IGNORED) { 621 if (opt_T || options.summary) { 622 calc_time_spent(event->proc); 623 } 624 } 625 event->proc->return_addr = brk_addr; 626 627 struct library_symbol *libsym = 628 event->proc->callstack[i].c_un.libfunc; 629 630 arch_symbol_ret(event->proc, libsym); 631 output_right_tos(event->proc); 632 callstack_pop(event->proc); 633 634 /* Pop also any other entries that seem like 635 * they are linked to the current one: they 636 * have the same return address, but were made 637 * for different symbols. This should only 638 * happen for entry point tracing, i.e. for -x 639 * everywhere, or -x and -e on MIPS. */ 640 while (event->proc->callstack_depth > 0) { 641 struct callstack_element *prev; 642 size_t d = event->proc->callstack_depth; 643 prev = &event->proc->callstack[d - 1]; 644 645 if (prev->c_un.libfunc == libsym 646 || prev->return_addr != brk_addr) 647 break; 648 649 arch_symbol_ret(event->proc, 650 prev->c_un.libfunc); 651 output_right_tos(event->proc); 652 callstack_pop(event->proc); 653 } 654 655 /* Maybe the previous callstack_pop's got rid 656 * of the breakpoint, but if we are in a 657 * recursive call, it's still enabled. In 658 * that case we need to skip it properly. */ 659 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) { 660 continue_after_breakpoint(event->proc, sbp); 661 } else { 662 set_instruction_pointer(event->proc, brk_addr); 663 continue_process(event->proc->pid); 664 } 665 return; 666 } 667 } 668 669 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) 670 breakpoint_on_hit(sbp, event->proc); 671 else if (event->proc->state != STATE_IGNORED) 672 output_line(event->proc, 673 "unexpected breakpoint at %p", brk_addr); 674 675 /* breakpoint_on_hit may delete its own breakpoint, so we have 676 * to look it up again. */ 677 if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) { 678 if (event->proc->state != STATE_IGNORED 679 && sbp->libsym != NULL) { 680 event->proc->stack_pointer = get_stack_pointer(event->proc); 681 event->proc->return_addr = 682 get_return_addr(event->proc, event->proc->stack_pointer); 683 callstack_push_symfunc(event->proc, sbp->libsym); 684 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym); 685 } 686 687 breakpoint_on_continue(sbp, event->proc); 688 return; 689 } else { 690 set_instruction_pointer(event->proc, brk_addr); 691 } 692 693 continue_process(event->proc->pid); 694} 695 696static void 697callstack_push_syscall(struct process *proc, int sysnum) 698{ 699 struct callstack_element *elem; 700 701 debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum); 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 = 1; 712 elem->c_un.syscall = sysnum; 713 elem->return_addr = NULL; 714 715 proc->callstack_depth++; 716 if (opt_T || options.summary) { 717 struct timezone tz; 718 gettimeofday(&elem->time_spent, &tz); 719 } 720} 721 722static void 723callstack_push_symfunc(struct process *proc, struct library_symbol *sym) 724{ 725 struct callstack_element *elem; 726 727 debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name); 728 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 729 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 730 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 731 abort(); 732 return; 733 } 734 735 elem = &proc->callstack[proc->callstack_depth++]; 736 *elem = (struct callstack_element){}; 737 elem->is_syscall = 0; 738 elem->c_un.libfunc = sym; 739 740 arch_addr_t return_addr = get_return_addr(proc, proc->stack_pointer); 741 struct breakpoint *rbp = NULL; 742 if (return_addr != 0) 743 rbp = insert_breakpoint(proc, return_addr, NULL); 744 elem->return_addr = rbp != NULL ? rbp->addr : 0; 745 746 if (opt_T || options.summary) { 747 struct timezone tz; 748 gettimeofday(&elem->time_spent, &tz); 749 } 750} 751 752void 753callstack_pop(struct process *proc) 754{ 755 struct callstack_element *elem; 756 assert(proc->callstack_depth > 0); 757 758 debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid); 759 elem = &proc->callstack[proc->callstack_depth - 1]; 760 if (!elem->is_syscall && elem->return_addr) 761 delete_breakpoint(proc, elem->return_addr); 762 763 if (elem->fetch_context != NULL) 764 fetch_arg_done(elem->fetch_context); 765 766 if (elem->arguments != NULL) { 767 val_dict_destroy(elem->arguments); 768 free(elem->arguments); 769 } 770 771 proc->callstack_depth--; 772} 773