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