handle_event.c revision 0b55b5852b9fe2ed6cceada004db303fe6efe6ce
1#define _GNU_SOURCE 2#include "config.h" 3 4#include <stdio.h> 5#include <string.h> 6#include <stdlib.h> 7#include <signal.h> 8#include <assert.h> 9#include <sys/time.h> 10#include <errno.h> 11 12#ifdef __powerpc__ 13#include <sys/ptrace.h> 14#endif 15 16#include "common.h" 17#include "breakpoint.h" 18#include "proc.h" 19#include "library.h" 20 21static void handle_signal(Event *event); 22static void handle_exit(Event *event); 23static void handle_exit_signal(Event *event); 24static void handle_syscall(Event *event); 25static void handle_arch_syscall(Event *event); 26static void handle_sysret(Event *event); 27static void handle_arch_sysret(Event *event); 28static void handle_clone(Event *event); 29static void handle_exec(Event *event); 30static void handle_breakpoint(Event *event); 31static void handle_new(Event *event); 32 33static void callstack_push_syscall(Process *proc, int sysnum); 34static void callstack_push_symfunc(Process *proc, 35 struct library_symbol *sym); 36static void callstack_pop(Process *proc); 37 38static char * shortsignal(Process *proc, int signum); 39static char * sysname(Process *proc, int sysnum); 40static char * arch_sysname(Process *proc, int sysnum); 41 42static Event * 43call_handler(Process * proc, Event * event) 44{ 45 assert(proc != NULL); 46 47 struct event_handler *handler = proc->event_handler; 48 if (handler == NULL) 49 return event; 50 51 return (*handler->on_event) (handler, event); 52} 53 54void 55handle_event(Event *event) 56{ 57 if (exiting == 1) { 58 debug(1, "ltrace about to exit"); 59 os_ltrace_exiting(); 60 exiting = 2; 61 } 62 debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)", 63 event->proc ? event->proc->pid : -1, event->type); 64 65 /* If the thread group or an individual task define an 66 overriding event handler, give them a chance to kick in. 67 We will end up calling both handlers, if the first one 68 doesn't sink the event. */ 69 if (event->proc != NULL) { 70 event = call_handler(event->proc, event); 71 if (event == NULL) 72 /* It was handled. */ 73 return; 74 75 /* Note: the previous handler has a chance to alter 76 * the event. */ 77 if (event->proc != NULL 78 && event->proc->leader != NULL 79 && event->proc != event->proc->leader) { 80 event = call_handler(event->proc->leader, event); 81 if (event == NULL) 82 return; 83 } 84 } 85 86 switch (event->type) { 87 case EVENT_NONE: 88 debug(1, "event: none"); 89 return; 90 case EVENT_SIGNAL: 91 debug(1, "event: signal (%s [%d])", 92 shortsignal(event->proc, event->e_un.signum), 93 event->e_un.signum); 94 handle_signal(event); 95 return; 96 case EVENT_EXIT: 97 debug(1, "event: exit (%d)", event->e_un.ret_val); 98 handle_exit(event); 99 return; 100 case EVENT_EXIT_SIGNAL: 101 debug(1, "event: exit signal (%s [%d])", 102 shortsignal(event->proc, event->e_un.signum), 103 event->e_un.signum); 104 handle_exit_signal(event); 105 return; 106 case EVENT_SYSCALL: 107 debug(1, "event: syscall (%s [%d])", 108 sysname(event->proc, event->e_un.sysnum), 109 event->e_un.sysnum); 110 handle_syscall(event); 111 return; 112 case EVENT_SYSRET: 113 debug(1, "event: sysret (%s [%d])", 114 sysname(event->proc, event->e_un.sysnum), 115 event->e_un.sysnum); 116 handle_sysret(event); 117 return; 118 case EVENT_ARCH_SYSCALL: 119 debug(1, "event: arch_syscall (%s [%d])", 120 arch_sysname(event->proc, event->e_un.sysnum), 121 event->e_un.sysnum); 122 handle_arch_syscall(event); 123 return; 124 case EVENT_ARCH_SYSRET: 125 debug(1, "event: arch_sysret (%s [%d])", 126 arch_sysname(event->proc, event->e_un.sysnum), 127 event->e_un.sysnum); 128 handle_arch_sysret(event); 129 return; 130 case EVENT_CLONE: 131 case EVENT_VFORK: 132 debug(1, "event: clone (%u)", event->e_un.newpid); 133 handle_clone(event); 134 return; 135 case EVENT_EXEC: 136 debug(1, "event: exec()"); 137 handle_exec(event); 138 return; 139 case EVENT_BREAKPOINT: 140 debug(1, "event: breakpoint"); 141 handle_breakpoint(event); 142 return; 143 case EVENT_NEW: 144 debug(1, "event: new process"); 145 handle_new(event); 146 return; 147 default: 148 fprintf(stderr, "Error! unknown event?\n"); 149 exit(1); 150 } 151} 152 153typedef struct Pending_New Pending_New; 154struct Pending_New { 155 pid_t pid; 156 Pending_New * next; 157}; 158static Pending_New * pending_news = NULL; 159 160static int 161pending_new(pid_t pid) { 162 Pending_New * p; 163 164 debug(DEBUG_FUNCTION, "pending_new(%d)", pid); 165 166 p = pending_news; 167 while (p) { 168 if (p->pid == pid) { 169 return 1; 170 } 171 p = p->next; 172 } 173 return 0; 174} 175 176static void 177pending_new_insert(pid_t pid) { 178 Pending_New * p; 179 180 debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid); 181 182 p = malloc(sizeof(Pending_New)); 183 if (!p) { 184 perror("malloc()"); 185 exit(1); 186 } 187 p->pid = pid; 188 p->next = pending_news; 189 pending_news = p; 190} 191 192static void 193pending_new_remove(pid_t pid) { 194 Pending_New *p, *pred; 195 196 debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid); 197 198 p = pending_news; 199 if (p->pid == pid) { 200 pending_news = p->next; 201 free(p); 202 } else { 203 while (p) { 204 if (p->pid == pid) { 205 pred->next = p->next; 206 free(p); 207 } 208 pred = p; 209 p = p->next; 210 } 211 } 212} 213 214#if 0 215static int 216clone_breakpoints(Process * proc, Process * orig_proc) 217{ 218 /* When copying breakpoints, we also have to copy the 219 * referenced symbols, and link them properly. */ 220 Dict * map = dict_init(&dict_key2hash_int, &dict_key_cmp_int); 221 struct library_symbol * it = proc->list_of_symbols; 222 proc->list_of_symbols = NULL; 223 for (; it != NULL; it = it->next) { 224 struct library_symbol * libsym = clone_library_symbol(it); 225 if (libsym == NULL) { 226 int save_errno; 227 err: 228 save_errno = errno; 229 destroy_library_symbol_chain(proc->list_of_symbols); 230 dict_clear(map); 231 errno = save_errno; 232 return -1; 233 } 234 libsym->next = proc->list_of_symbols; 235 proc->list_of_symbols = libsym; 236 if (dict_enter(map, it, libsym) != 0) 237 goto err; 238 } 239 240 proc->breakpoints = dict_clone2(orig_proc->breakpoints, 241 address_clone, breakpoint_clone, map); 242 if (proc->breakpoints == NULL) 243 goto err; 244 245 dict_clear(map); 246 return 0; 247} 248#endif 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 /* XXX proper error handling here, please. */ 260 perror("malloc()"); 261 exit(1); 262 } 263 264 if (process_clone(proc, event->proc, event->e_un.newpid) < 0) 265 goto fail; 266 proc->parent = event->proc; 267 268 /* We save register values to the arch pointer, and these need 269 to be per-thread. */ 270 proc->arch_ptr = NULL; 271 272 if (pending_new(proc->pid)) { 273 pending_new_remove(proc->pid); 274 /* XXX this used to be destroy_event_handler call, but 275 * I don't think we want to call that on a shared 276 * state. */ 277 proc->event_handler = NULL; 278 if (event->proc->state == STATE_ATTACHED && options.follow) 279 proc->state = STATE_ATTACHED; 280 else 281 proc->state = STATE_IGNORED; 282 continue_process(proc->pid); 283 } else { 284 proc->state = STATE_BEING_CREATED; 285 } 286 add_process(proc); 287 288 if (event->type == EVENT_VFORK) 289 continue_after_vfork(proc); 290 else 291 continue_process(event->proc->pid); 292} 293 294static void 295handle_new(Event * event) { 296 Process * proc; 297 298 debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid); 299 300 proc = pid2proc(event->e_un.newpid); 301 if (!proc) { 302 pending_new_insert(event->e_un.newpid); 303 } else { 304 assert(proc->state == STATE_BEING_CREATED); 305 if (options.follow) { 306 proc->state = STATE_ATTACHED; 307 } else { 308 proc->state = STATE_IGNORED; 309 } 310 continue_process(proc->pid); 311 } 312} 313 314static char * 315shortsignal(Process *proc, int signum) { 316 static char *signalent0[] = { 317#include "signalent.h" 318 }; 319 static char *signalent1[] = { 320#include "signalent1.h" 321 }; 322 static char **signalents[] = { signalent0, signalent1 }; 323 int nsignals[] = { sizeof signalent0 / sizeof signalent0[0], 324 sizeof signalent1 / sizeof signalent1[0] 325 }; 326 327 debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum); 328 329 if (proc->personality > sizeof signalents / sizeof signalents[0]) 330 abort(); 331 if (signum < 0 || signum >= nsignals[proc->personality]) { 332 return "UNKNOWN_SIGNAL"; 333 } else { 334 return signalents[proc->personality][signum]; 335 } 336} 337 338static char * 339sysname(Process *proc, int sysnum) { 340 static char result[128]; 341 static char *syscalent0[] = { 342#include "syscallent.h" 343 }; 344 static char *syscalent1[] = { 345#include "syscallent1.h" 346 }; 347 static char **syscalents[] = { syscalent0, syscalent1 }; 348 int nsyscals[] = { sizeof syscalent0 / sizeof syscalent0[0], 349 sizeof syscalent1 / sizeof syscalent1[0] 350 }; 351 352 debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 353 354 if (proc->personality > sizeof syscalents / sizeof syscalents[0]) 355 abort(); 356 if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) { 357 sprintf(result, "SYS_%d", sysnum); 358 return result; 359 } else { 360 sprintf(result, "SYS_%s", 361 syscalents[proc->personality][sysnum]); 362 return result; 363 } 364} 365 366static char * 367arch_sysname(Process *proc, int sysnum) { 368 static char result[128]; 369 static char *arch_syscalent[] = { 370#include "arch_syscallent.h" 371 }; 372 int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0]; 373 374 debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum); 375 376 if (sysnum < 0 || sysnum >= nsyscals) { 377 sprintf(result, "ARCH_%d", sysnum); 378 return result; 379 } else { 380 sprintf(result, "ARCH_%s", 381 arch_syscalent[sysnum]); 382 return result; 383 } 384} 385 386static void 387handle_signal(Event *event) { 388 debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); 389 if (event->proc->state != STATE_IGNORED && !options.no_signals) { 390 output_line(event->proc, "--- %s (%s) ---", 391 shortsignal(event->proc, event->e_un.signum), 392 strsignal(event->e_un.signum)); 393 } 394 continue_after_signal(event->proc->pid, event->e_un.signum); 395} 396 397static void 398handle_exit(Event *event) { 399 debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val); 400 if (event->proc->state != STATE_IGNORED) { 401 output_line(event->proc, "+++ exited (status %d) +++", 402 event->e_un.ret_val); 403 } 404 remove_process(event->proc); 405 free(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 free(event->proc); 417} 418 419static struct library_symbol * 420temporary_syscall_symbol(const char *name) 421{ 422 struct library *syscalls = malloc(sizeof(*syscalls)); 423 struct library_symbol *syscall = malloc(sizeof(*syscall)); 424 if (syscalls == NULL || syscall == NULL) { 425 free(syscalls); 426 free(syscall); 427 return NULL; 428 } 429 library_init(syscalls); 430 library_set_soname(syscalls, "SYS", 0); 431 library_symbol_init(syscall, 0, name, 0, LS_TOPLT_NONE); 432 library_add_symbol(syscalls, syscall); 433 return syscall; 434} 435 436static void 437output_syscall_left(struct Process *proc, const char *name) 438{ 439 struct library_symbol *syscall = temporary_syscall_symbol(name); 440 output_left(LT_TOF_SYSCALL, proc, syscall); 441 struct library *lib = syscall->lib; 442 library_destroy(lib); 443 free(lib); 444} 445 446static void 447output_syscall_right(struct Process *proc, const char *name) 448{ 449 struct library_symbol *syscall = temporary_syscall_symbol(name); 450 output_right(LT_TOF_SYSCALLR, proc, syscall); 451 struct library *lib = syscall->lib; 452 library_destroy(lib); 453 free(lib); 454} 455 456static void 457handle_syscall(Event *event) { 458 debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 459 if (event->proc->state != STATE_IGNORED) { 460 callstack_push_syscall(event->proc, event->e_un.sysnum); 461 if (options.syscalls) 462 output_syscall_left(event->proc, 463 sysname(event->proc, 464 event->e_un.sysnum)); 465 } 466 continue_after_syscall(event->proc, event->e_un.sysnum, 0); 467} 468 469static void 470handle_exec(Event * event) { 471 Process * proc = event->proc; 472 473 debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid); 474 if (proc->state == STATE_IGNORED) { 475 untrace_pid(proc->pid); 476 remove_process(proc); 477 free(proc); 478 return; 479 } 480 output_line(proc, "--- Called exec() ---"); 481 proc->mask_32bit = 0; 482 proc->personality = 0; 483 proc->arch_ptr = NULL; 484 free(proc->filename); 485 proc->filename = pid2name(proc->pid); 486 breakpoints_init(proc, 0); 487 proc->callstack_depth = 0; 488 continue_process(proc->pid); 489} 490 491static void 492handle_arch_syscall(Event *event) { 493 debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 494 if (event->proc->state != STATE_IGNORED) { 495 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); 496 if (options.syscalls) { 497 output_syscall_left(event->proc, 498 arch_sysname(event->proc, 499 event->e_un.sysnum)); 500 } 501 } 502 continue_process(event->proc->pid); 503} 504 505struct timeval current_time_spent; 506 507static void 508calc_time_spent(Process *proc) { 509 struct timeval tv; 510 struct timezone tz; 511 struct timeval diff; 512 struct callstack_element *elem; 513 514 debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid); 515 elem = &proc->callstack[proc->callstack_depth - 1]; 516 517 gettimeofday(&tv, &tz); 518 519 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec; 520 if (tv.tv_usec >= elem->time_spent.tv_usec) { 521 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec; 522 } else { 523 diff.tv_sec++; 524 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec; 525 } 526 current_time_spent = diff; 527} 528 529static void 530handle_sysret(Event *event) { 531 debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 532 if (event->proc->state != STATE_IGNORED) { 533 if (opt_T || options.summary) { 534 calc_time_spent(event->proc); 535 } 536 if (options.syscalls) 537 output_syscall_right(event->proc, 538 sysname(event->proc, 539 event->e_un.sysnum)); 540 541 assert(event->proc->callstack_depth > 0); 542 unsigned d = event->proc->callstack_depth - 1; 543 assert(event->proc->callstack[d].is_syscall); 544 callstack_pop(event->proc); 545 } 546 continue_after_syscall(event->proc, event->e_un.sysnum, 1); 547} 548 549static void 550handle_arch_sysret(Event *event) { 551 debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 552 if (event->proc->state != STATE_IGNORED) { 553 if (opt_T || options.summary) { 554 calc_time_spent(event->proc); 555 } 556 if (options.syscalls) 557 output_syscall_right(event->proc, 558 arch_sysname(event->proc, 559 event->e_un.sysnum)); 560 callstack_pop(event->proc); 561 } 562 continue_process(event->proc->pid); 563} 564 565static void 566output_right_tos(struct Process *proc) 567{ 568 size_t d = proc->callstack_depth; 569 struct callstack_element *elem = &proc->callstack[d - 1]; 570 if (proc->state != STATE_IGNORED) 571 output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc->name); 572} 573 574static void 575handle_breakpoint(Event *event) 576{ 577 int i, j; 578 struct breakpoint *sbp; 579 Process *leader = event->proc->leader; 580 void *brk_addr = event->e_un.brk_addr; 581 582 /* The leader has terminated. */ 583 if (leader == NULL) { 584 continue_process(event->proc->pid); 585 return; 586 } 587 588 debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", 589 event->proc->pid, brk_addr); 590 debug(2, "event: breakpoint (%p)", brk_addr); 591 592 for (i = event->proc->callstack_depth - 1; i >= 0; i--) { 593 if (brk_addr == event->proc->callstack[i].return_addr) { 594#ifdef __powerpc__ 595 /* 596 * PPC HACK! (XXX FIXME TODO) 597 * The PLT gets modified during the first call, 598 * so be sure to re-enable the breakpoint. 599 */ 600 unsigned long a; 601 struct library_symbol *libsym = 602 event->proc->callstack[i].c_un.libfunc; 603 void *addr = sym2addr(event->proc, libsym); 604 605 if (libsym->plt_type != LS_TOPLT_POINT) { 606 unsigned char break_insn[] = BREAKPOINT_VALUE; 607 608 sbp = address2bpstruct(leader, addr); 609 assert(sbp); 610 a = ptrace(PTRACE_PEEKTEXT, event->proc->pid, 611 addr); 612 613 if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) { 614 sbp->enabled--; 615 insert_breakpoint(event->proc, addr, 616 libsym); 617 } 618 } else { 619 sbp = dict_find_entry(leader->breakpoints, addr); 620 /* On powerpc, the breakpoint address 621 may end up being actual entry point 622 of the library symbol, not the PLT 623 address we computed. In that case, 624 sbp is NULL. */ 625 if (sbp == NULL || addr != sbp->addr) { 626 insert_breakpoint(event->proc, addr, 627 libsym); 628 } 629 } 630#elif defined(__mips__) 631 void *addr = NULL; 632 struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc; 633 struct library_symbol *new_sym; 634 assert(sym); 635 addr = sym2addr(event->proc, sym); 636 sbp = dict_find_entry(leader->breakpoints, addr); 637 if (sbp) { 638 if (addr != sbp->addr) { 639 insert_breakpoint(event->proc, addr, sym); 640 } 641 } else { 642 new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1); 643 memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1); 644 new_sym->next = leader->list_of_symbols; 645 leader->list_of_symbols = new_sym; 646 insert_breakpoint(event->proc, addr, new_sym); 647 } 648#endif 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 event->proc->return_addr = brk_addr; 658 659 output_right_tos(event->proc); 660 callstack_pop(event->proc); 661 662 /* Pop also any other entries that seem like 663 * they are linked to the current one: they 664 * have the same return address, but were made 665 * for different symbols. This should only 666 * happen for entry point tracing, i.e. for -x 667 * everywhere, or -x and -e on PPC64. */ 668 while (event->proc->callstack_depth > 0) { 669 struct callstack_element *prev; 670 size_t d = event->proc->callstack_depth; 671 prev = &event->proc->callstack[d - 1]; 672 673 if (prev->c_un.libfunc == libsym 674 || prev->return_addr != brk_addr) 675 break; 676 677 output_right_tos(event->proc); 678 callstack_pop(event->proc); 679 } 680 681 sbp = address2bpstruct(leader, brk_addr); 682 continue_after_breakpoint(event->proc, sbp); 683 return; 684 } 685 } 686 687 if ((sbp = address2bpstruct(leader, brk_addr))) { 688 breakpoint_on_hit(sbp, event->proc); 689 690 if (event->proc->state != STATE_IGNORED 691 && sbp->libsym != NULL) { 692 event->proc->stack_pointer = get_stack_pointer(event->proc); 693 event->proc->return_addr = 694 get_return_addr(event->proc, event->proc->stack_pointer); 695 callstack_push_symfunc(event->proc, sbp->libsym); 696 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym); 697 } 698 699 breakpoint_on_continue(sbp, event->proc); 700 return; 701 } 702 703 if (event->proc->state != STATE_IGNORED && !options.no_plt) { 704 output_line(event->proc, "unexpected breakpoint at %p", 705 brk_addr); 706 } 707 continue_process(event->proc->pid); 708} 709 710static void 711callstack_push_syscall(Process *proc, int sysnum) { 712 struct callstack_element *elem; 713 714 debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum); 715 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 716 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 717 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 718 abort(); 719 return; 720 } 721 722 elem = &proc->callstack[proc->callstack_depth]; 723 elem->is_syscall = 1; 724 elem->c_un.syscall = sysnum; 725 elem->return_addr = NULL; 726 727 proc->callstack_depth++; 728 if (opt_T || options.summary) { 729 struct timezone tz; 730 gettimeofday(&elem->time_spent, &tz); 731 } 732} 733 734static void 735callstack_push_symfunc(Process *proc, struct library_symbol *sym) { 736 struct callstack_element *elem; 737 738 debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name); 739 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 740 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 741 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 742 abort(); 743 return; 744 } 745 746 elem = &proc->callstack[proc->callstack_depth++]; 747 elem->is_syscall = 0; 748 elem->c_un.libfunc = sym; 749 750 elem->return_addr = proc->return_addr; 751 if (elem->return_addr) 752 insert_breakpoint(proc, elem->return_addr, NULL); 753 754 /* handle functions like atexit() on mips which have no return */ 755 if (opt_T || options.summary) { 756 struct timezone tz; 757 gettimeofday(&elem->time_spent, &tz); 758 } 759} 760 761static void 762callstack_pop(Process *proc) { 763 struct callstack_element *elem; 764 assert(proc->callstack_depth > 0); 765 766 debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid); 767 elem = &proc->callstack[proc->callstack_depth - 1]; 768 if (!elem->is_syscall && elem->return_addr) { 769 assert(proc->leader != NULL); 770 delete_breakpoint(proc, elem->return_addr); 771 } 772 if (elem->arch_ptr != NULL) { 773 free(elem->arch_ptr); 774 elem->arch_ptr = NULL; 775 } 776 proc->callstack_depth--; 777} 778