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