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