handle_event.c revision 1429874dee5758cc99c0dae73bd3f928109e53d7
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 18static void handle_signal(Event *event); 19static void handle_exit(Event *event); 20static void handle_exit_signal(Event *event); 21static void handle_syscall(Event *event); 22static void handle_arch_syscall(Event *event); 23static void handle_sysret(Event *event); 24static void handle_arch_sysret(Event *event); 25static void handle_clone(Event *event); 26static void handle_exec(Event *event); 27static void handle_breakpoint(Event *event); 28static void handle_new(Event *event); 29 30static void callstack_push_syscall(Process *proc, int sysnum); 31static void callstack_push_symfunc(Process *proc, 32 struct library_symbol *sym); 33static void callstack_pop(Process *proc); 34 35static char * shortsignal(Process *proc, int signum); 36static char * sysname(Process *proc, int sysnum); 37static char * arch_sysname(Process *proc, int sysnum); 38 39static Event * 40call_handler(Process * proc, Event * event) 41{ 42 assert(proc != NULL); 43 44 Event_Handler * handler = proc->event_handler; 45 if (handler == NULL) 46 return event; 47 48 return (*handler->on_event) (handler, event); 49} 50 51void 52handle_event(Event *event) 53{ 54 if (exiting == 1) { 55 debug(1, "ltrace about to exit"); 56 os_ltrace_exiting(); 57 exiting = 2; 58 } 59 debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)", 60 event->proc ? event->proc->pid : -1, event->type); 61 62 /* If the thread group or an individual task define an 63 overriding event handler, give them a chance to kick in. 64 We will end up calling both handlers, if the first one 65 doesn't sink the event. */ 66 if (event->proc != NULL) { 67 event = call_handler(event->proc, event); 68 if (event == NULL) 69 /* It was handled. */ 70 return; 71 72 /* Note: the previous handler has a chance to alter 73 * the event. */ 74 if (event->proc != NULL 75 && event->proc->leader != NULL 76 && event->proc != event->proc->leader) { 77 event = call_handler(event->proc->leader, event); 78 if (event == NULL) 79 return; 80 } 81 } 82 83 switch (event->type) { 84 case EVENT_NONE: 85 debug(1, "event: none"); 86 return; 87 case EVENT_SIGNAL: 88 debug(1, "event: signal (%s [%d])", 89 shortsignal(event->proc, event->e_un.signum), 90 event->e_un.signum); 91 handle_signal(event); 92 return; 93 case EVENT_EXIT: 94 debug(1, "event: exit (%d)", event->e_un.ret_val); 95 handle_exit(event); 96 return; 97 case EVENT_EXIT_SIGNAL: 98 debug(1, "event: exit signal (%s [%d])", 99 shortsignal(event->proc, event->e_un.signum), 100 event->e_un.signum); 101 handle_exit_signal(event); 102 return; 103 case EVENT_SYSCALL: 104 debug(1, "event: syscall (%s [%d])", 105 sysname(event->proc, event->e_un.sysnum), 106 event->e_un.sysnum); 107 handle_syscall(event); 108 return; 109 case EVENT_SYSRET: 110 debug(1, "event: sysret (%s [%d])", 111 sysname(event->proc, event->e_un.sysnum), 112 event->e_un.sysnum); 113 handle_sysret(event); 114 return; 115 case EVENT_ARCH_SYSCALL: 116 debug(1, "event: arch_syscall (%s [%d])", 117 arch_sysname(event->proc, event->e_un.sysnum), 118 event->e_un.sysnum); 119 handle_arch_syscall(event); 120 return; 121 case EVENT_ARCH_SYSRET: 122 debug(1, "event: arch_sysret (%s [%d])", 123 arch_sysname(event->proc, event->e_un.sysnum), 124 event->e_un.sysnum); 125 handle_arch_sysret(event); 126 return; 127 case EVENT_CLONE: 128 case EVENT_VFORK: 129 debug(1, "event: clone (%u)", event->e_un.newpid); 130 handle_clone(event); 131 return; 132 case EVENT_EXEC: 133 debug(1, "event: exec()"); 134 handle_exec(event); 135 return; 136 case EVENT_BREAKPOINT: 137 debug(1, "event: breakpoint"); 138 handle_breakpoint(event); 139 return; 140 case EVENT_NEW: 141 debug(1, "event: new process"); 142 handle_new(event); 143 return; 144 default: 145 fprintf(stderr, "Error! unknown event?\n"); 146 exit(1); 147 } 148} 149 150/* TODO */ 151static void * 152address_clone(void * addr, void * data) 153{ 154 debug(DEBUG_FUNCTION, "address_clone(%p)", addr); 155 return addr; 156} 157 158static void * 159breakpoint_clone(void *bp, void *data) 160{ 161 Breakpoint * b; 162 Dict *map = data; 163 debug(DEBUG_FUNCTION, "breakpoint_clone(%p)", bp); 164 b = malloc(sizeof(Breakpoint)); 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 if (event->proc->breakpoints_enabled == 0) { 457 enable_all_breakpoints(event->proc); 458 } 459 } 460 continue_after_syscall(event->proc, event->e_un.sysnum, 0); 461} 462 463static void 464handle_exec(Event * event) { 465 Process * proc = event->proc; 466 pid_t saved_pid; 467 468 debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid); 469 if (proc->state == STATE_IGNORED) { 470 untrace_pid(proc->pid); 471 remove_process(proc); 472 return; 473 } 474 output_line(proc, "--- Called exec() ---"); 475 proc->mask_32bit = 0; 476 proc->personality = 0; 477 proc->arch_ptr = NULL; 478 free(proc->filename); 479 proc->filename = pid2name(proc->pid); 480 saved_pid = proc->pid; 481 proc->pid = 0; 482 breakpoints_init(proc, 0); 483 proc->pid = saved_pid; 484 proc->callstack_depth = 0; 485 continue_process(proc->pid); 486} 487 488static void 489handle_arch_syscall(Event *event) { 490 debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 491 if (event->proc->state != STATE_IGNORED) { 492 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); 493 if (options.syscalls) { 494 output_left(LT_TOF_SYSCALL, event->proc, 495 arch_sysname(event->proc, event->e_un.sysnum)); 496 } 497 if (event->proc->breakpoints_enabled == 0) { 498 enable_all_breakpoints(event->proc); 499 } 500 } 501 continue_process(event->proc->pid); 502} 503 504struct timeval current_time_spent; 505 506static void 507calc_time_spent(Process *proc) { 508 struct timeval tv; 509 struct timezone tz; 510 struct timeval diff; 511 struct callstack_element *elem; 512 513 debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid); 514 elem = &proc->callstack[proc->callstack_depth - 1]; 515 516 gettimeofday(&tv, &tz); 517 518 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec; 519 if (tv.tv_usec >= elem->time_spent.tv_usec) { 520 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec; 521 } else { 522 diff.tv_sec++; 523 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec; 524 } 525 current_time_spent = diff; 526} 527 528static void 529handle_sysret(Event *event) { 530 debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 531 if (event->proc->state != STATE_IGNORED) { 532 if (opt_T || options.summary) { 533 calc_time_spent(event->proc); 534 } 535 if (options.syscalls) { 536 output_right(LT_TOF_SYSCALLR, event->proc, 537 sysname(event->proc, event->e_un.sysnum)); 538 } 539 assert(event->proc->callstack_depth > 0); 540 unsigned d = event->proc->callstack_depth - 1; 541 assert(event->proc->callstack[d].is_syscall); 542 callstack_pop(event->proc); 543 } 544 continue_after_syscall(event->proc, event->e_un.sysnum, 1); 545} 546 547static void 548handle_arch_sysret(Event *event) { 549 debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); 550 if (event->proc->state != STATE_IGNORED) { 551 if (opt_T || options.summary) { 552 calc_time_spent(event->proc); 553 } 554 if (options.syscalls) { 555 output_right(LT_TOF_SYSCALLR, event->proc, 556 arch_sysname(event->proc, event->e_un.sysnum)); 557 } 558 callstack_pop(event->proc); 559 } 560 continue_process(event->proc->pid); 561} 562 563#ifdef __powerpc__ 564void *get_count_register (Process *proc); 565#endif 566 567static void 568output_right_tos(struct Process *proc) 569{ 570 size_t d = proc->callstack_depth; 571 struct callstack_element *elem = &proc->callstack[d - 1]; 572 if (proc->state != STATE_IGNORED) 573 output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc->name); 574} 575 576static void 577handle_breakpoint(Event *event) 578{ 579 int i, j; 580 Breakpoint *sbp; 581 Process *leader = event->proc->leader; 582 void *brk_addr = event->e_un.brk_addr; 583 584 /* The leader has terminated. */ 585 if (leader == NULL) { 586 continue_process(event->proc->pid); 587 return; 588 } 589 590 debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", 591 event->proc->pid, brk_addr); 592 debug(2, "event: breakpoint (%p)", brk_addr); 593 594#ifdef __powerpc__ 595 /* Need to skip following NOP's to prevent a fake function from being stacked. */ 596 long stub_addr = (long) get_count_register(event->proc); 597 Breakpoint *stub_bp = NULL; 598 char nop_instruction[] = PPC_NOP; 599 600 stub_bp = address2bpstruct(leader, brk_addr); 601 602 if (stub_bp) { 603 unsigned char *bp_instruction = stub_bp->orig_value; 604 605 if (memcmp(bp_instruction, nop_instruction, 606 PPC_NOP_LENGTH) == 0) { 607 if (stub_addr != (long) brk_addr) { 608 set_instruction_pointer(event->proc, 609 brk_addr + 4); 610 continue_process(event->proc->pid); 611 return; 612 } 613 } 614 } 615#endif 616 617 for (i = event->proc->callstack_depth - 1; i >= 0; i--) { 618 if (brk_addr == event->proc->callstack[i].return_addr) { 619#ifdef __powerpc__ 620 /* 621 * PPC HACK! (XXX FIXME TODO) 622 * The PLT gets modified during the first call, 623 * so be sure to re-enable the breakpoint. 624 */ 625 unsigned long a; 626 struct library_symbol *libsym = 627 event->proc->callstack[i].c_un.libfunc; 628 void *addr = sym2addr(event->proc, libsym); 629 630 if (libsym->plt_type != LS_TOPLT_POINT) { 631 unsigned char break_insn[] = BREAKPOINT_VALUE; 632 633 sbp = address2bpstruct(leader, addr); 634 assert(sbp); 635 a = ptrace(PTRACE_PEEKTEXT, event->proc->pid, 636 addr); 637 638 if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) { 639 sbp->enabled--; 640 insert_breakpoint(event->proc, addr, 641 libsym, 1); 642 } 643 } else { 644 sbp = dict_find_entry(leader->breakpoints, addr); 645 /* On powerpc, the breakpoint address 646 may end up being actual entry point 647 of the library symbol, not the PLT 648 address we computed. In that case, 649 sbp is NULL. */ 650 if (sbp == NULL || addr != sbp->addr) { 651 insert_breakpoint(event->proc, addr, 652 libsym, 1); 653 } 654 } 655#elif defined(__mips__) 656 void *addr = NULL; 657 struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc; 658 struct library_symbol *new_sym; 659 assert(sym); 660 addr = sym2addr(event->proc, sym); 661 sbp = dict_find_entry(leader->breakpoints, addr); 662 if (sbp) { 663 if (addr != sbp->addr) { 664 insert_breakpoint(event->proc, addr, sym, 1); 665 } 666 } else { 667 new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1); 668 memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1); 669 new_sym->next = leader->list_of_symbols; 670 leader->list_of_symbols = new_sym; 671 insert_breakpoint(event->proc, addr, new_sym, 1); 672 } 673#endif 674 for (j = event->proc->callstack_depth - 1; j > i; j--) { 675 callstack_pop(event->proc); 676 } 677 if (event->proc->state != STATE_IGNORED) { 678 if (opt_T || options.summary) { 679 calc_time_spent(event->proc); 680 } 681 } 682 event->proc->return_addr = brk_addr; 683 684 output_right_tos(event->proc); 685 callstack_pop(event->proc); 686 687 /* Pop also any other entries that seem like 688 * they are linked to the current one: they 689 * have the same return address, but were made 690 * for different symbols. This should only 691 * happen for entry point tracing, i.e. for -x 692 * everywhere, or -x and -e on PPC64. */ 693 while (event->proc->callstack_depth > 0) { 694 struct callstack_element *prev; 695 size_t d = event->proc->callstack_depth; 696 prev = &event->proc->callstack[d - 1]; 697 698 if (prev->c_un.libfunc == libsym 699 || prev->return_addr != brk_addr) 700 break; 701 702 output_right_tos(event->proc); 703 callstack_pop(event->proc); 704 } 705 706 sbp = address2bpstruct(leader, brk_addr); 707 continue_after_breakpoint(event->proc, sbp); 708 return; 709 } 710 } 711 712 if ((sbp = address2bpstruct(leader, brk_addr))) { 713 if (sbp->libsym == NULL) { 714 continue_after_breakpoint(event->proc, sbp); 715 return; 716 } 717 718 if (strcmp(sbp->libsym->name, "") == 0) { 719 debug(DEBUG_PROCESS, "Hit _dl_debug_state breakpoint!\n"); 720 arch_check_dbg(leader); 721 } 722 723 if (event->proc->state != STATE_IGNORED) { 724 event->proc->stack_pointer = get_stack_pointer(event->proc); 725 event->proc->return_addr = 726 get_return_addr(event->proc, event->proc->stack_pointer); 727 callstack_push_symfunc(event->proc, sbp->libsym); 728 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name); 729 } 730#ifdef PLT_REINITALISATION_BP 731 if (event->proc->need_to_reinitialize_breakpoints 732 && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) == 733 0)) 734 reinitialize_breakpoints(leader); 735#endif 736 737 continue_after_breakpoint(event->proc, sbp); 738 return; 739 } 740 741 if (event->proc->state != STATE_IGNORED && !options.no_plt) { 742 output_line(event->proc, "unexpected breakpoint at %p", 743 brk_addr); 744 } 745 continue_process(event->proc->pid); 746} 747 748static void 749callstack_push_syscall(Process *proc, int sysnum) { 750 struct callstack_element *elem; 751 752 debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum); 753 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 754 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 755 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 756 abort(); 757 return; 758 } 759 760 elem = &proc->callstack[proc->callstack_depth]; 761 elem->is_syscall = 1; 762 elem->c_un.syscall = sysnum; 763 elem->return_addr = NULL; 764 765 proc->callstack_depth++; 766 if (opt_T || options.summary) { 767 struct timezone tz; 768 gettimeofday(&elem->time_spent, &tz); 769 } 770} 771 772static void 773callstack_push_symfunc(Process *proc, struct library_symbol *sym) { 774 struct callstack_element *elem; 775 776 debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name); 777 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */ 778 if (proc->callstack_depth == MAX_CALLDEPTH - 1) { 779 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__); 780 abort(); 781 return; 782 } 783 784 elem = &proc->callstack[proc->callstack_depth++]; 785 elem->is_syscall = 0; 786 elem->c_un.libfunc = sym; 787 788 elem->return_addr = proc->return_addr; 789 if (elem->return_addr) { 790 insert_breakpoint(proc, elem->return_addr, NULL, 1); 791 } 792 793 /* handle functions like atexit() on mips which have no return */ 794 if (opt_T || options.summary) { 795 struct timezone tz; 796 gettimeofday(&elem->time_spent, &tz); 797 } 798} 799 800static void 801callstack_pop(Process *proc) { 802 struct callstack_element *elem; 803 assert(proc->callstack_depth > 0); 804 805 debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid); 806 elem = &proc->callstack[proc->callstack_depth - 1]; 807 if (!elem->is_syscall && elem->return_addr) { 808 assert(proc->leader != NULL); 809 delete_breakpoint(proc, elem->return_addr); 810 } 811 if (elem->arch_ptr != NULL) { 812 free(elem->arch_ptr); 813 elem->arch_ptr = NULL; 814 } 815 proc->callstack_depth--; 816} 817