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