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