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