strace.c revision e18314ed0fc97ed9df74944d755a9be63075178c
1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $Id$ 31 */ 32 33#include "defs.h" 34 35#include <sys/types.h> 36#include <stdarg.h> 37#include <signal.h> 38#include <errno.h> 39#include <sys/param.h> 40#include <fcntl.h> 41#include <sys/resource.h> 42#include <sys/wait.h> 43#include <sys/stat.h> 44#include <pwd.h> 45#include <grp.h> 46#include <string.h> 47#include <limits.h> 48#include <dirent.h> 49 50#ifdef LINUX 51# include <asm/unistd.h> 52# if defined __NR_tgkill 53# define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig)) 54# elif defined __NR_tkill 55# define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig)) 56# else 57 /* kill() may choose arbitrarily the target task of the process group 58 while we later wait on a that specific TID. PID process waits become 59 TID task specific waits for a process under ptrace(2). */ 60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!" 61# define my_tgkill(pid, tid, sig) kill((tid), (sig)) 62# endif 63#endif 64 65#if defined(IA64) && defined(LINUX) 66# include <asm/ptrace_offsets.h> 67#endif 68 69#ifdef USE_PROCFS 70#include <poll.h> 71#endif 72 73#ifdef SVR4 74#include <sys/stropts.h> 75#ifdef HAVE_MP_PROCFS 76#ifdef HAVE_SYS_UIO_H 77#include <sys/uio.h> 78#endif 79#endif 80#endif 81extern char **environ; 82extern int optind; 83extern char *optarg; 84 85 86int debug = 0, followfork = 0; 87unsigned int ptrace_setoptions = 0; 88/* Which WSTOPSIG(status) value marks syscall traps? */ 89static unsigned int syscall_trap_sig = SIGTRAP; 90int dtime = 0, xflag = 0, qflag = 0; 91cflag_t cflag = CFLAG_NONE; 92static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0; 93/* 94 * daemonized_tracer supports -D option. 95 * With this option, strace forks twice. 96 * Unlike normal case, with -D *grandparent* process exec's, 97 * becoming a traced process. Child exits (this prevents traced process 98 * from having children it doesn't expect to have), and grandchild 99 * attaches to grandparent similarly to strace -p PID. 100 * This allows for more transparent interaction in cases 101 * when process and its parent are communicating via signals, 102 * wait() etc. Without -D, strace process gets lodged in between, 103 * disrupting parent<->child link. 104 */ 105static bool daemonized_tracer = 0; 106 107/* Sometimes we want to print only succeeding syscalls. */ 108int not_failing_only = 0; 109 110/* Show path associated with fd arguments */ 111int show_fd_path = 0; 112 113/* are we filtering traces based on paths? */ 114int tracing_paths = 0; 115 116static int exit_code = 0; 117static int strace_child = 0; 118static int strace_tracer_pid = 0; 119 120static char *username = NULL; 121static uid_t run_uid; 122static gid_t run_gid; 123 124int acolumn = DEFAULT_ACOLUMN; 125int max_strlen = DEFAULT_STRLEN; 126static char *outfname = NULL; 127static FILE *outf; 128static int curcol; 129static struct tcb **tcbtab; 130static unsigned int nprocs, tcbtabsize; 131static const char *progname; 132 133static int detach(struct tcb *tcp, int sig); 134static int trace(void); 135static void cleanup(void); 136static void interrupt(int sig); 137static sigset_t empty_set, blocked_set; 138 139#ifdef HAVE_SIG_ATOMIC_T 140static volatile sig_atomic_t interrupted; 141#else /* !HAVE_SIG_ATOMIC_T */ 142static volatile int interrupted; 143#endif /* !HAVE_SIG_ATOMIC_T */ 144 145#ifdef USE_PROCFS 146 147static struct tcb *pfd2tcb(int pfd); 148static void reaper(int sig); 149static void rebuild_pollv(void); 150static struct pollfd *pollv; 151 152#ifndef HAVE_POLLABLE_PROCFS 153 154static void proc_poll_open(void); 155static void proc_poller(int pfd); 156 157struct proc_pollfd { 158 int fd; 159 int revents; 160 int pid; 161}; 162 163static int poller_pid; 164static int proc_poll_pipe[2] = { -1, -1 }; 165 166#endif /* !HAVE_POLLABLE_PROCFS */ 167 168#ifdef HAVE_MP_PROCFS 169#define POLLWANT POLLWRNORM 170#else 171#define POLLWANT POLLPRI 172#endif 173#endif /* USE_PROCFS */ 174 175static void 176usage(FILE *ofp, int exitval) 177{ 178 fprintf(ofp, "\ 179usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\ 180 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 181 [-P path] [command [arg ...]]\n\ 182 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 183 [command [arg ...]]\n\ 184-c -- count time, calls, and errors for each syscall and report summary\n\ 185-C -- like -c but also print regular output while processes are running\n\ 186-f -- follow forks, -ff -- with output into separate files\n\ 187-F -- attempt to follow vforks, -h -- print help message\n\ 188-i -- print instruction pointer at time of syscall\n\ 189-q -- suppress messages about attaching, detaching, etc.\n\ 190-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 191-T -- print time spent in each syscall, -V -- print version\n\ 192-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 193-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 194-y -- print paths associated with file descriptor arguments\n\ 195-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 196-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 197 options: trace, abbrev, verbose, raw, signal, read, or write\n\ 198-o file -- send trace output to FILE instead of stderr\n\ 199-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 200-p pid -- trace process with process id PID, may be repeated\n\ 201-D -- run tracer process as a detached grandchild, not as parent\n\ 202-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 203-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 204-u username -- run command as username handling setuid and/or setgid\n\ 205-E var=val -- put var=val in the environment for command\n\ 206-E var -- remove var from the environment for command\n\ 207-P path -- trace accesses to path\n\ 208" /* this is broken, so don't document it 209-z -- print only succeeding syscalls\n\ 210 */ 211, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 212 exit(exitval); 213} 214 215static void die(void) __attribute__ ((noreturn)); 216static void die(void) 217{ 218 if (strace_tracer_pid == getpid()) { 219 cflag = 0; 220 cleanup(); 221 } 222 exit(1); 223} 224 225static void verror_msg(int err_no, const char *fmt, va_list p) 226{ 227 fflush(NULL); 228 fprintf(stderr, "%s: ", progname); 229 vfprintf(stderr, fmt, p); 230 if (err_no) 231 fprintf(stderr, ": %s\n", strerror(err_no)); 232 else 233 putc('\n', stderr); 234 fflush(stderr); 235} 236 237void error_msg(const char *fmt, ...) 238{ 239 va_list p; 240 va_start(p, fmt); 241 verror_msg(0, fmt, p); 242 va_end(p); 243} 244 245void error_msg_and_die(const char *fmt, ...) 246{ 247 va_list p; 248 va_start(p, fmt); 249 verror_msg(0, fmt, p); 250 die(); 251} 252 253void perror_msg(const char *fmt, ...) 254{ 255 va_list p; 256 va_start(p, fmt); 257 verror_msg(errno, fmt, p); 258 va_end(p); 259} 260 261void perror_msg_and_die(const char *fmt, ...) 262{ 263 va_list p; 264 va_start(p, fmt); 265 verror_msg(errno, fmt, p); 266 die(); 267} 268 269#ifdef SVR4 270#ifdef MIPS 271void 272foobar() 273{ 274} 275#endif /* MIPS */ 276#endif /* SVR4 */ 277 278/* Glue for systems without a MMU that cannot provide fork() */ 279#ifdef HAVE_FORK 280# define strace_vforked 0 281#else 282# define strace_vforked 1 283# define fork() vfork() 284#endif 285 286static void 287set_cloexec_flag(int fd) 288{ 289 int flags, newflags; 290 291 flags = fcntl(fd, F_GETFD); 292 if (flags < 0) { 293 /* Can happen only if fd is bad. 294 * Should never happen: if it does, we have a bug 295 * in the caller. Therefore we just abort 296 * instead of propagating the error. 297 */ 298 perror_msg_and_die("fcntl(%d, F_GETFD)", fd); 299 } 300 301 newflags = flags | FD_CLOEXEC; 302 if (flags == newflags) 303 return; 304 305 fcntl(fd, F_SETFD, newflags); /* never fails */ 306} 307 308/* 309 * When strace is setuid executable, we have to swap uids 310 * before and after filesystem and process management operations. 311 */ 312static void 313swap_uid(void) 314{ 315#ifndef SVR4 316 int euid = geteuid(), uid = getuid(); 317 318 if (euid != uid && setreuid(euid, uid) < 0) { 319 perror_msg_and_die("setreuid"); 320 } 321#endif 322} 323 324#if _LFS64_LARGEFILE 325# define fopen_for_output fopen64 326#else 327# define fopen_for_output fopen 328#endif 329 330static FILE * 331strace_fopen(const char *path) 332{ 333 FILE *fp; 334 335 swap_uid(); 336 fp = fopen_for_output(path, "w"); 337 if (!fp) 338 perror_msg_and_die("Can't fopen '%s'", path); 339 swap_uid(); 340 set_cloexec_flag(fileno(fp)); 341 return fp; 342} 343 344static int popen_pid = 0; 345 346#ifndef _PATH_BSHELL 347# define _PATH_BSHELL "/bin/sh" 348#endif 349 350/* 351 * We cannot use standard popen(3) here because we have to distinguish 352 * popen child process from other processes we trace, and standard popen(3) 353 * does not export its child's pid. 354 */ 355static FILE * 356strace_popen(const char *command) 357{ 358 FILE *fp; 359 int fds[2]; 360 361 swap_uid(); 362 if (pipe(fds) < 0) 363 perror_msg_and_die("pipe"); 364 365 set_cloexec_flag(fds[1]); /* never fails */ 366 367 popen_pid = vfork(); 368 if (popen_pid == -1) 369 perror_msg_and_die("vfork"); 370 371 if (popen_pid == 0) { 372 /* child */ 373 close(fds[1]); 374 if (fds[0] != 0) { 375 if (dup2(fds[0], 0)) 376 perror_msg_and_die("dup2"); 377 close(fds[0]); 378 } 379 execl(_PATH_BSHELL, "sh", "-c", command, NULL); 380 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL); 381 } 382 383 /* parent */ 384 close(fds[0]); 385 swap_uid(); 386 fp = fdopen(fds[1], "w"); 387 if (!fp) 388 error_msg_and_die("Out of memory"); 389 return fp; 390} 391 392static void 393newoutf(struct tcb *tcp) 394{ 395 if (outfname && followfork > 1) { 396 char name[520 + sizeof(int) * 3]; 397 sprintf(name, "%.512s.%u", outfname, tcp->pid); 398 tcp->outf = strace_fopen(name); 399 } 400} 401 402static void 403startup_attach(void) 404{ 405 int tcbi; 406 struct tcb *tcp; 407 408 /* 409 * Block user interruptions as we would leave the traced 410 * process stopped (process state T) if we would terminate in 411 * between PTRACE_ATTACH and wait4 () on SIGSTOP. 412 * We rely on cleanup() from this point on. 413 */ 414 if (interactive) 415 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 416 417 if (daemonized_tracer) { 418 pid_t pid = fork(); 419 if (pid < 0) { 420 _exit(1); 421 } 422 if (pid) { /* parent */ 423 /* 424 * Wait for grandchild to attach to straced process 425 * (grandparent). Grandchild SIGKILLs us after it attached. 426 * Grandparent's wait() is unblocked by our death, 427 * it proceeds to exec the straced program. 428 */ 429 pause(); 430 _exit(0); /* paranoia */ 431 } 432 /* grandchild */ 433 /* We will be the tracer process. Remember our new pid: */ 434 strace_tracer_pid = getpid(); 435 } 436 437 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 438 tcp = tcbtab[tcbi]; 439 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 440 continue; 441#ifdef LINUX 442 if (tcp->flags & TCB_CLONE_THREAD) 443 continue; 444#endif 445 /* Reinitialize the output since it may have changed. */ 446 tcp->outf = outf; 447 newoutf(tcp); 448 449#ifdef USE_PROCFS 450 if (proc_open(tcp, 1) < 0) { 451 fprintf(stderr, "trouble opening proc file\n"); 452 droptcb(tcp); 453 continue; 454 } 455#else /* !USE_PROCFS */ 456# ifdef LINUX 457 if (followfork && !daemonized_tracer) { 458 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; 459 DIR *dir; 460 461 sprintf(procdir, "/proc/%d/task", tcp->pid); 462 dir = opendir(procdir); 463 if (dir != NULL) { 464 unsigned int ntid = 0, nerr = 0; 465 struct dirent *de; 466 int tid; 467 while ((de = readdir(dir)) != NULL) { 468 if (de->d_fileno == 0) 469 continue; 470 tid = atoi(de->d_name); 471 if (tid <= 0) 472 continue; 473 ++ntid; 474 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) { 475 ++nerr; 476 if (debug) 477 fprintf(stderr, "attach to pid %d failed\n", tid); 478 } 479 else { 480 if (debug) 481 fprintf(stderr, "attach to pid %d succeeded\n", tid); 482 if (tid != tcbtab[tcbi]->pid) { 483 tcp = alloctcb(tid); 484 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD; 485 tcbtab[tcbi]->nclone_threads++; 486 tcp->parent = tcbtab[tcbi]; 487 } 488 } 489 if (interactive) { 490 sigprocmask(SIG_SETMASK, &empty_set, NULL); 491 if (interrupted) 492 return; 493 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 494 } 495 } 496 closedir(dir); 497 ntid -= nerr; 498 if (ntid == 0) { 499 perror("attach: ptrace(PTRACE_ATTACH, ...)"); 500 droptcb(tcp); 501 continue; 502 } 503 if (!qflag) { 504 fprintf(stderr, ntid > 1 505? "Process %u attached with %u threads - interrupt to quit\n" 506: "Process %u attached - interrupt to quit\n", 507 tcbtab[tcbi]->pid, ntid); 508 } 509 continue; 510 } /* if (opendir worked) */ 511 } /* if (-f) */ 512# endif 513 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 514 perror("attach: ptrace(PTRACE_ATTACH, ...)"); 515 droptcb(tcp); 516 continue; 517 } 518 if (debug) 519 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid); 520 521 if (daemonized_tracer) { 522 /* 523 * It is our grandparent we trace, not a -p PID. 524 * Don't want to just detach on exit, so... 525 */ 526 tcp->flags &= ~TCB_ATTACHED; 527 /* 528 * Make parent go away. 529 * Also makes grandparent's wait() unblock. 530 */ 531 kill(getppid(), SIGKILL); 532 } 533 534#endif /* !USE_PROCFS */ 535 if (!qflag) 536 fprintf(stderr, 537 "Process %u attached - interrupt to quit\n", 538 tcp->pid); 539 } /* for each tcbtab[] */ 540 541 if (interactive) 542 sigprocmask(SIG_SETMASK, &empty_set, NULL); 543} 544 545static void 546startup_child(char **argv) 547{ 548 struct stat statbuf; 549 const char *filename; 550 char pathname[MAXPATHLEN]; 551 int pid = 0; 552 struct tcb *tcp; 553 554 filename = argv[0]; 555 if (strchr(filename, '/')) { 556 if (strlen(filename) > sizeof pathname - 1) { 557 errno = ENAMETOOLONG; 558 perror_msg_and_die("exec"); 559 } 560 strcpy(pathname, filename); 561 } 562#ifdef USE_DEBUGGING_EXEC 563 /* 564 * Debuggers customarily check the current directory 565 * first regardless of the path but doing that gives 566 * security geeks a panic attack. 567 */ 568 else if (stat(filename, &statbuf) == 0) 569 strcpy(pathname, filename); 570#endif /* USE_DEBUGGING_EXEC */ 571 else { 572 const char *path; 573 int m, n, len; 574 575 for (path = getenv("PATH"); path && *path; path += m) { 576 if (strchr(path, ':')) { 577 n = strchr(path, ':') - path; 578 m = n + 1; 579 } 580 else 581 m = n = strlen(path); 582 if (n == 0) { 583 if (!getcwd(pathname, MAXPATHLEN)) 584 continue; 585 len = strlen(pathname); 586 } 587 else if (n > sizeof pathname - 1) 588 continue; 589 else { 590 strncpy(pathname, path, n); 591 len = n; 592 } 593 if (len && pathname[len - 1] != '/') 594 pathname[len++] = '/'; 595 strcpy(pathname + len, filename); 596 if (stat(pathname, &statbuf) == 0 && 597 /* Accept only regular files 598 with some execute bits set. 599 XXX not perfect, might still fail */ 600 S_ISREG(statbuf.st_mode) && 601 (statbuf.st_mode & 0111)) 602 break; 603 } 604 } 605 if (stat(pathname, &statbuf) < 0) { 606 perror_msg_and_die("Can't stat '%s'", filename); 607 } 608 strace_child = pid = fork(); 609 if (pid < 0) { 610 perror_msg_and_die("fork"); 611 } 612 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */ 613 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */ 614 ) { 615 pid = getpid(); 616#ifdef USE_PROCFS 617 if (outf != stderr) close(fileno(outf)); 618#ifdef MIPS 619 /* Kludge for SGI, see proc_open for details. */ 620 sa.sa_handler = foobar; 621 sa.sa_flags = 0; 622 sigemptyset(&sa.sa_mask); 623 sigaction(SIGINT, &sa, NULL); 624#endif /* MIPS */ 625#ifndef FREEBSD 626 pause(); 627#else /* FREEBSD */ 628 kill(pid, SIGSTOP); /* stop HERE */ 629#endif /* FREEBSD */ 630#else /* !USE_PROCFS */ 631 if (outf != stderr) 632 close(fileno(outf)); 633 634 if (!daemonized_tracer) { 635 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 636 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)"); 637 } 638 if (debug) 639 kill(pid, SIGSTOP); 640 } 641 642 if (username != NULL || geteuid() == 0) { 643 uid_t run_euid = run_uid; 644 gid_t run_egid = run_gid; 645 646 if (statbuf.st_mode & S_ISUID) 647 run_euid = statbuf.st_uid; 648 if (statbuf.st_mode & S_ISGID) 649 run_egid = statbuf.st_gid; 650 651 /* 652 * It is important to set groups before we 653 * lose privileges on setuid. 654 */ 655 if (username != NULL) { 656 if (initgroups(username, run_gid) < 0) { 657 perror_msg_and_die("initgroups"); 658 } 659 if (setregid(run_gid, run_egid) < 0) { 660 perror_msg_and_die("setregid"); 661 } 662 if (setreuid(run_uid, run_euid) < 0) { 663 perror_msg_and_die("setreuid"); 664 } 665 } 666 } 667 else 668 setreuid(run_uid, run_uid); 669 670 if (!daemonized_tracer) { 671 /* 672 * Induce an immediate stop so that the parent 673 * will resume us with PTRACE_SYSCALL and display 674 * this execve call normally. 675 * Unless of course we're on a no-MMU system where 676 * we vfork()-ed, so we cannot stop the child. 677 */ 678 if (!strace_vforked) 679 kill(getpid(), SIGSTOP); 680 } else { 681 struct sigaction sv_sigchld; 682 sigaction(SIGCHLD, NULL, &sv_sigchld); 683 /* 684 * Make sure it is not SIG_IGN, otherwise wait 685 * will not block. 686 */ 687 signal(SIGCHLD, SIG_DFL); 688 /* 689 * Wait for grandchild to attach to us. 690 * It kills child after that, and wait() unblocks. 691 */ 692 alarm(3); 693 wait(NULL); 694 alarm(0); 695 sigaction(SIGCHLD, &sv_sigchld, NULL); 696 } 697#endif /* !USE_PROCFS */ 698 699 execv(pathname, argv); 700 perror_msg_and_die("exec"); 701 } 702 703 /* We are the tracer. */ 704 /* With -D, we are *child* here, IOW: different pid. Fetch it. */ 705 strace_tracer_pid = getpid(); 706 707 tcp = alloctcb(daemonized_tracer ? getppid() : pid); 708 if (daemonized_tracer) { 709 /* We want subsequent startup_attach() to attach to it. */ 710 tcp->flags |= TCB_ATTACHED; 711 } 712#ifdef USE_PROCFS 713 if (proc_open(tcp, 0) < 0) { 714 perror_msg_and_die("trouble opening proc file"); 715 } 716#endif /* USE_PROCFS */ 717} 718 719#ifdef LINUX 720/* 721 * Test whether the kernel support PTRACE_O_TRACECLONE et al options. 722 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it, 723 * and then see which options are supported by the kernel. 724 */ 725static int 726test_ptrace_setoptions_followfork(void) 727{ 728 int pid, expected_grandchild = 0, found_grandchild = 0; 729 const unsigned int test_options = PTRACE_O_TRACECLONE | 730 PTRACE_O_TRACEFORK | 731 PTRACE_O_TRACEVFORK; 732 733 if ((pid = fork()) < 0) 734 return -1; 735 else if (pid == 0) { 736 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0) 737 _exit(1); 738 kill(getpid(), SIGSTOP); 739 _exit(fork() < 0); 740 } 741 742 while (1) { 743 int status, tracee_pid; 744 745 tracee_pid = wait(&status); 746 if (tracee_pid == -1) { 747 if (errno == EINTR) 748 continue; 749 else if (errno == ECHILD) 750 break; 751 perror("test_ptrace_setoptions_followfork"); 752 return -1; 753 } 754 if (tracee_pid != pid) { 755 found_grandchild = tracee_pid; 756 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 && 757 errno != ESRCH) 758 kill(tracee_pid, SIGKILL); 759 } 760 else if (WIFSTOPPED(status)) { 761 switch (WSTOPSIG(status)) { 762 case SIGSTOP: 763 if (ptrace(PTRACE_SETOPTIONS, pid, 764 NULL, test_options) < 0) { 765 kill(pid, SIGKILL); 766 return -1; 767 } 768 break; 769 case SIGTRAP: 770 if (status >> 16 == PTRACE_EVENT_FORK) { 771 long msg = 0; 772 773 if (ptrace(PTRACE_GETEVENTMSG, pid, 774 NULL, (long) &msg) == 0) 775 expected_grandchild = msg; 776 } 777 break; 778 } 779 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 && 780 errno != ESRCH) 781 kill(pid, SIGKILL); 782 } 783 } 784 if (expected_grandchild && expected_grandchild == found_grandchild) 785 ptrace_setoptions |= test_options; 786 return 0; 787} 788 789/* 790 * Test whether the kernel support PTRACE_O_TRACESYSGOOD. 791 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it, 792 * and then see whether it will stop with (SIGTRAP | 0x80). 793 * 794 * Use of this option enables correct handling of user-generated SIGTRAPs, 795 * and SIGTRAPs generated by special instructions such as int3 on x86: 796 * _start: .globl _start 797 * int3 798 * movl $42, %ebx 799 * movl $1, %eax 800 * int $0x80 801 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S") 802 */ 803static void 804test_ptrace_setoptions_for_all(void) 805{ 806 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC; 807 int pid; 808 int it_worked = 0; 809 810 pid = fork(); 811 if (pid < 0) 812 perror_msg_and_die("fork"); 813 814 if (pid == 0) { 815 pid = getpid(); 816 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) 817 /* Note: exits with exitcode 1 */ 818 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__); 819 kill(pid, SIGSTOP); 820 _exit(0); /* parent should see entry into this syscall */ 821 } 822 823 while (1) { 824 int status, tracee_pid; 825 826 errno = 0; 827 tracee_pid = wait(&status); 828 if (tracee_pid <= 0) { 829 if (errno == EINTR) 830 continue; 831 kill(pid, SIGKILL); 832 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid); 833 } 834 if (WIFEXITED(status)) { 835 if (WEXITSTATUS(status) == 0) 836 break; 837 /* PTRACE_TRACEME failed in child. This is fatal. */ 838 exit(1); 839 } 840 if (!WIFSTOPPED(status)) { 841 kill(pid, SIGKILL); 842 error_msg_and_die("%s: unexpected wait status %x", __func__, status); 843 } 844 if (WSTOPSIG(status) == SIGSTOP) { 845 /* 846 * We don't check "options aren't accepted" error. 847 * If it happens, we'll never get (SIGTRAP | 0x80), 848 * and thus will decide to not use the option. 849 * IOW: the outcome of the test will be correct. 850 */ 851 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0) 852 if (errno != EINVAL) 853 perror_msg("PTRACE_SETOPTIONS"); 854 } 855 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) { 856 it_worked = 1; 857 } 858 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) { 859 kill(pid, SIGKILL); 860 perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 861 } 862 } 863 864 if (it_worked) { 865 syscall_trap_sig = (SIGTRAP | 0x80); 866 ptrace_setoptions |= test_options; 867 if (debug) 868 fprintf(stderr, "ptrace_setoptions = %#x\n", 869 ptrace_setoptions); 870 return; 871 } 872 873 fprintf(stderr, 874 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n"); 875} 876#endif 877 878int 879main(int argc, char *argv[]) 880{ 881 struct tcb *tcp; 882 int c, pid = 0; 883 int optF = 0; 884 struct sigaction sa; 885 886 progname = argv[0] ? argv[0] : "strace"; 887 888 strace_tracer_pid = getpid(); 889 890 /* Allocate the initial tcbtab. */ 891 tcbtabsize = argc; /* Surely enough for all -p args. */ 892 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0])); 893 if (tcbtab == NULL) 894 error_msg_and_die("Out of memory"); 895 tcp = calloc(tcbtabsize, sizeof(*tcp)); 896 if (tcp == NULL) 897 error_msg_and_die("Out of memory"); 898 for (c = 0; c < tcbtabsize; c++) 899 tcbtab[c] = tcp++; 900 901 outf = stderr; 902 interactive = 1; 903 set_sortby(DEFAULT_SORTBY); 904 set_personality(DEFAULT_PERSONALITY); 905 qualify("trace=all"); 906 qualify("abbrev=all"); 907 qualify("verbose=all"); 908 qualify("signal=all"); 909 while ((c = getopt(argc, argv, 910 "+cCdfFhiqrtTvVxyz" 911#ifndef USE_PROCFS 912 "D" 913#endif 914 "a:e:o:O:p:s:S:u:E:P:")) != EOF) { 915 switch (c) { 916 case 'c': 917 if (cflag == CFLAG_BOTH) { 918 error_msg_and_die("-c and -C are mutually exclusive options"); 919 } 920 cflag = CFLAG_ONLY_STATS; 921 break; 922 case 'C': 923 if (cflag == CFLAG_ONLY_STATS) { 924 error_msg_and_die("-c and -C are mutually exclusive options"); 925 } 926 cflag = CFLAG_BOTH; 927 break; 928 case 'd': 929 debug++; 930 break; 931#ifndef USE_PROCFS 932 case 'D': 933 daemonized_tracer = 1; 934 break; 935#endif 936 case 'F': 937 optF = 1; 938 break; 939 case 'f': 940 followfork++; 941 break; 942 case 'h': 943 usage(stdout, 0); 944 break; 945 case 'i': 946 iflag++; 947 break; 948 case 'q': 949 qflag++; 950 break; 951 case 'r': 952 rflag++; 953 tflag++; 954 break; 955 case 't': 956 tflag++; 957 break; 958 case 'T': 959 dtime++; 960 break; 961 case 'x': 962 xflag++; 963 break; 964 case 'y': 965 show_fd_path = 1; 966 break; 967 case 'v': 968 qualify("abbrev=none"); 969 break; 970 case 'V': 971 printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 972 exit(0); 973 break; 974 case 'z': 975 not_failing_only = 1; 976 break; 977 case 'a': 978 acolumn = atoi(optarg); 979 break; 980 case 'e': 981 qualify(optarg); 982 break; 983 case 'o': 984 outfname = strdup(optarg); 985 break; 986 case 'O': 987 set_overhead(atoi(optarg)); 988 break; 989 case 'p': 990 if ((pid = atoi(optarg)) <= 0) { 991 error_msg("Invalid process id: '%s'", optarg); 992 break; 993 } 994 if (pid == strace_tracer_pid) { 995 error_msg("I'm sorry, I can't let you do that, Dave."); 996 break; 997 } 998 tcp = alloc_tcb(pid, 0); 999 tcp->flags |= TCB_ATTACHED; 1000 pflag_seen++; 1001 break; 1002 case 'P': 1003 tracing_paths = 1; 1004 if (pathtrace_select(optarg)) { 1005 error_msg_and_die("Failed to select path '%s'", optarg); 1006 } 1007 break; 1008 case 's': 1009 max_strlen = atoi(optarg); 1010 if (max_strlen < 0) { 1011 error_msg_and_die("Invalid -s argument: '%s'", optarg); 1012 } 1013 break; 1014 case 'S': 1015 set_sortby(optarg); 1016 break; 1017 case 'u': 1018 username = strdup(optarg); 1019 break; 1020 case 'E': 1021 if (putenv(optarg) < 0) { 1022 error_msg_and_die("Out of memory"); 1023 } 1024 break; 1025 default: 1026 usage(stderr, 1); 1027 break; 1028 } 1029 } 1030 1031 if ((optind == argc) == !pflag_seen) 1032 usage(stderr, 1); 1033 1034 if (pflag_seen && daemonized_tracer) { 1035 error_msg_and_die("-D and -p are mutually exclusive options"); 1036 } 1037 1038 if (!followfork) 1039 followfork = optF; 1040 1041 if (followfork > 1 && cflag) { 1042 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options"); 1043 } 1044 1045 /* See if they want to run as another user. */ 1046 if (username != NULL) { 1047 struct passwd *pent; 1048 1049 if (getuid() != 0 || geteuid() != 0) { 1050 error_msg_and_die("You must be root to use the -u option"); 1051 } 1052 if ((pent = getpwnam(username)) == NULL) { 1053 error_msg_and_die("Cannot find user '%s'", username); 1054 } 1055 run_uid = pent->pw_uid; 1056 run_gid = pent->pw_gid; 1057 } 1058 else { 1059 run_uid = getuid(); 1060 run_gid = getgid(); 1061 } 1062 1063#ifdef LINUX 1064 if (followfork) { 1065 if (test_ptrace_setoptions_followfork() < 0) { 1066 fprintf(stderr, 1067 "Test for options supported by PTRACE_SETOPTIONS " 1068 "failed, giving up using this feature.\n"); 1069 ptrace_setoptions = 0; 1070 } 1071 if (debug) 1072 fprintf(stderr, "ptrace_setoptions = %#x\n", 1073 ptrace_setoptions); 1074 } 1075 test_ptrace_setoptions_for_all(); 1076#endif 1077 1078 /* Check if they want to redirect the output. */ 1079 if (outfname) { 1080 /* See if they want to pipe the output. */ 1081 if (outfname[0] == '|' || outfname[0] == '!') { 1082 /* 1083 * We can't do the <outfname>.PID funny business 1084 * when using popen, so prohibit it. 1085 */ 1086 if (followfork > 1) 1087 error_msg_and_die("Piping the output and -ff are mutually exclusive"); 1088 outf = strace_popen(outfname + 1); 1089 } 1090 else if (followfork <= 1) 1091 outf = strace_fopen(outfname); 1092 } 1093 1094 if (!outfname || outfname[0] == '|' || outfname[0] == '!') { 1095 static char buf[BUFSIZ]; 1096 setvbuf(outf, buf, _IOLBF, BUFSIZ); 1097 } 1098 if (outfname && optind < argc) { 1099 interactive = 0; 1100 qflag = 1; 1101 } 1102 1103 /* Valid states here: 1104 optind < argc pflag_seen outfname interactive 1105 1 0 0 1 1106 0 1 0 1 1107 1 0 1 0 1108 0 1 1 1 1109 */ 1110 1111 /* STARTUP_CHILD must be called before the signal handlers get 1112 installed below as they are inherited into the spawned process. 1113 Also we do not need to be protected by them as during interruption 1114 in the STARTUP_CHILD mode we kill the spawned process anyway. */ 1115 if (!pflag_seen) 1116 startup_child(&argv[optind]); 1117 1118 sigemptyset(&empty_set); 1119 sigemptyset(&blocked_set); 1120 sa.sa_handler = SIG_IGN; 1121 sigemptyset(&sa.sa_mask); 1122 sa.sa_flags = 0; 1123 sigaction(SIGTTOU, &sa, NULL); 1124 sigaction(SIGTTIN, &sa, NULL); 1125 if (interactive) { 1126 sigaddset(&blocked_set, SIGHUP); 1127 sigaddset(&blocked_set, SIGINT); 1128 sigaddset(&blocked_set, SIGQUIT); 1129 sigaddset(&blocked_set, SIGPIPE); 1130 sigaddset(&blocked_set, SIGTERM); 1131 sa.sa_handler = interrupt; 1132#ifdef SUNOS4 1133 /* POSIX signals on sunos4.1 are a little broken. */ 1134 sa.sa_flags = SA_INTERRUPT; 1135#endif /* SUNOS4 */ 1136 } 1137 sigaction(SIGHUP, &sa, NULL); 1138 sigaction(SIGINT, &sa, NULL); 1139 sigaction(SIGQUIT, &sa, NULL); 1140 sigaction(SIGPIPE, &sa, NULL); 1141 sigaction(SIGTERM, &sa, NULL); 1142#ifdef USE_PROCFS 1143 sa.sa_handler = reaper; 1144 sigaction(SIGCHLD, &sa, NULL); 1145#else 1146 /* Make sure SIGCHLD has the default action so that waitpid 1147 definitely works without losing track of children. The user 1148 should not have given us a bogus state to inherit, but he might 1149 have. Arguably we should detect SIG_IGN here and pass it on 1150 to children, but probably noone really needs that. */ 1151 sa.sa_handler = SIG_DFL; 1152 sigaction(SIGCHLD, &sa, NULL); 1153#endif /* USE_PROCFS */ 1154 1155 if (pflag_seen || daemonized_tracer) 1156 startup_attach(); 1157 1158 if (trace() < 0) 1159 exit(1); 1160 cleanup(); 1161 fflush(NULL); 1162 if (exit_code > 0xff) { 1163 /* Child was killed by a signal, mimic that. */ 1164 exit_code &= 0xff; 1165 signal(exit_code, SIG_DFL); 1166 raise(exit_code); 1167 /* Paranoia - what if this signal is not fatal? 1168 Exit with 128 + signo then. */ 1169 exit_code += 128; 1170 } 1171 exit(exit_code); 1172} 1173 1174static void 1175expand_tcbtab(void) 1176{ 1177 /* Allocate some more TCBs and expand the table. 1178 We don't want to relocate the TCBs because our 1179 callers have pointers and it would be a pain. 1180 So tcbtab is a table of pointers. Since we never 1181 free the TCBs, we allocate a single chunk of many. */ 1182 int i = tcbtabsize; 1183 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0])); 1184 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0])); 1185 if (newtab == NULL || newtcbs == NULL) 1186 error_msg_and_die("expand_tcbtab: out of memory"); 1187 tcbtabsize *= 2; 1188 tcbtab = newtab; 1189 while (i < tcbtabsize) 1190 tcbtab[i++] = newtcbs++; 1191} 1192 1193struct tcb * 1194alloc_tcb(int pid, int command_options_parsed) 1195{ 1196 int i; 1197 struct tcb *tcp; 1198 1199 if (nprocs == tcbtabsize) 1200 expand_tcbtab(); 1201 1202 for (i = 0; i < tcbtabsize; i++) { 1203 tcp = tcbtab[i]; 1204 if ((tcp->flags & TCB_INUSE) == 0) { 1205 memset(tcp, 0, sizeof(*tcp)); 1206 tcp->pid = pid; 1207 tcp->flags = TCB_INUSE | TCB_STARTUP; 1208 tcp->outf = outf; /* Initialise to current out file */ 1209 tcp->pfd = -1; 1210 nprocs++; 1211 if (debug) 1212 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs); 1213 if (command_options_parsed) 1214 newoutf(tcp); 1215 return tcp; 1216 } 1217 } 1218 error_msg_and_die("bug in alloc_tcb"); 1219} 1220 1221#ifdef USE_PROCFS 1222int 1223proc_open(struct tcb *tcp, int attaching) 1224{ 1225 char proc[32]; 1226 long arg; 1227#ifdef SVR4 1228 int i; 1229 sysset_t syscalls; 1230 sigset_t signals; 1231 fltset_t faults; 1232#endif 1233#ifndef HAVE_POLLABLE_PROCFS 1234 static int last_pfd; 1235#endif 1236 1237#ifdef HAVE_MP_PROCFS 1238 /* Open the process pseudo-files in /proc. */ 1239 sprintf(proc, "/proc/%d/ctl", tcp->pid); 1240 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 1241 perror("strace: open(\"/proc/...\", ...)"); 1242 return -1; 1243 } 1244 set_cloexec_flag(tcp->pfd); 1245 sprintf(proc, "/proc/%d/status", tcp->pid); 1246 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 1247 perror("strace: open(\"/proc/...\", ...)"); 1248 return -1; 1249 } 1250 set_cloexec_flag(tcp->pfd_stat); 1251 sprintf(proc, "/proc/%d/as", tcp->pid); 1252 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 1253 perror("strace: open(\"/proc/...\", ...)"); 1254 return -1; 1255 } 1256 set_cloexec_flag(tcp->pfd_as); 1257#else 1258 /* Open the process pseudo-file in /proc. */ 1259#ifndef FREEBSD 1260 sprintf(proc, "/proc/%d", tcp->pid); 1261 tcp->pfd = open(proc, O_RDWR|O_EXCL); 1262#else /* FREEBSD */ 1263 sprintf(proc, "/proc/%d/mem", tcp->pid); 1264 tcp->pfd = open(proc, O_RDWR); 1265#endif /* FREEBSD */ 1266 if (tcp->pfd < 0) { 1267 perror("strace: open(\"/proc/...\", ...)"); 1268 return -1; 1269 } 1270 set_cloexec_flag(tcp->pfd); 1271#endif 1272#ifdef FREEBSD 1273 sprintf(proc, "/proc/%d/regs", tcp->pid); 1274 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 1275 perror("strace: open(\"/proc/.../regs\", ...)"); 1276 return -1; 1277 } 1278 if (cflag) { 1279 sprintf(proc, "/proc/%d/status", tcp->pid); 1280 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 1281 perror("strace: open(\"/proc/.../status\", ...)"); 1282 return -1; 1283 } 1284 } else 1285 tcp->pfd_status = -1; 1286#endif /* FREEBSD */ 1287 rebuild_pollv(); 1288 if (!attaching) { 1289 /* 1290 * Wait for the child to pause. Because of a race 1291 * condition we have to poll for the event. 1292 */ 1293 for (;;) { 1294 if (IOCTL_STATUS(tcp) < 0) { 1295 perror("strace: PIOCSTATUS"); 1296 return -1; 1297 } 1298 if (tcp->status.PR_FLAGS & PR_ASLEEP) 1299 break; 1300 } 1301 } 1302#ifndef FREEBSD 1303 /* Stop the process so that we own the stop. */ 1304 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 1305 perror("strace: PIOCSTOP"); 1306 return -1; 1307 } 1308#endif 1309#ifdef PIOCSET 1310 /* Set Run-on-Last-Close. */ 1311 arg = PR_RLC; 1312 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 1313 perror("PIOCSET PR_RLC"); 1314 return -1; 1315 } 1316 /* Set or Reset Inherit-on-Fork. */ 1317 arg = PR_FORK; 1318 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 1319 perror("PIOC{SET,RESET} PR_FORK"); 1320 return -1; 1321 } 1322#else /* !PIOCSET */ 1323#ifndef FREEBSD 1324 if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 1325 perror("PIOCSRLC"); 1326 return -1; 1327 } 1328 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 1329 perror("PIOC{S,R}FORK"); 1330 return -1; 1331 } 1332#else /* FREEBSD */ 1333 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 1334 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 1335 perror("PIOCGFL"); 1336 return -1; 1337 } 1338 arg &= ~PF_LINGER; 1339 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 1340 perror("PIOCSFL"); 1341 return -1; 1342 } 1343#endif /* FREEBSD */ 1344#endif /* !PIOCSET */ 1345#ifndef FREEBSD 1346 /* Enable all syscall entries we care about. */ 1347 premptyset(&syscalls); 1348 for (i = 1; i < MAX_QUALS; ++i) { 1349 if (i > (sizeof syscalls) * CHAR_BIT) break; 1350 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i); 1351 } 1352 praddset(&syscalls, SYS_execve); 1353 if (followfork) { 1354 praddset(&syscalls, SYS_fork); 1355#ifdef SYS_forkall 1356 praddset(&syscalls, SYS_forkall); 1357#endif 1358#ifdef SYS_fork1 1359 praddset(&syscalls, SYS_fork1); 1360#endif 1361#ifdef SYS_rfork1 1362 praddset(&syscalls, SYS_rfork1); 1363#endif 1364#ifdef SYS_rforkall 1365 praddset(&syscalls, SYS_rforkall); 1366#endif 1367 } 1368 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 1369 perror("PIOCSENTRY"); 1370 return -1; 1371 } 1372 /* Enable the syscall exits. */ 1373 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 1374 perror("PIOSEXIT"); 1375 return -1; 1376 } 1377 /* Enable signals we care about. */ 1378 premptyset(&signals); 1379 for (i = 1; i < MAX_QUALS; ++i) { 1380 if (i > (sizeof signals) * CHAR_BIT) break; 1381 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i); 1382 } 1383 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 1384 perror("PIOCSTRACE"); 1385 return -1; 1386 } 1387 /* Enable faults we care about */ 1388 premptyset(&faults); 1389 for (i = 1; i < MAX_QUALS; ++i) { 1390 if (i > (sizeof faults) * CHAR_BIT) break; 1391 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i); 1392 } 1393 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 1394 perror("PIOCSFAULT"); 1395 return -1; 1396 } 1397#else /* FREEBSD */ 1398 /* set events flags. */ 1399 arg = S_SIG | S_SCE | S_SCX; 1400 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 1401 perror("PIOCBIS"); 1402 return -1; 1403 } 1404#endif /* FREEBSD */ 1405 if (!attaching) { 1406#ifdef MIPS 1407 /* 1408 * The SGI PRSABORT doesn't work for pause() so 1409 * we send it a caught signal to wake it up. 1410 */ 1411 kill(tcp->pid, SIGINT); 1412#else /* !MIPS */ 1413#ifdef PRSABORT 1414 /* The child is in a pause(), abort it. */ 1415 arg = PRSABORT; 1416 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1417 perror("PIOCRUN"); 1418 return -1; 1419 } 1420#endif 1421#endif /* !MIPS*/ 1422#ifdef FREEBSD 1423 /* wake up the child if it received the SIGSTOP */ 1424 kill(tcp->pid, SIGCONT); 1425#endif 1426 for (;;) { 1427 /* Wait for the child to do something. */ 1428 if (IOCTL_WSTOP(tcp) < 0) { 1429 perror("PIOCWSTOP"); 1430 return -1; 1431 } 1432 if (tcp->status.PR_WHY == PR_SYSENTRY) { 1433 tcp->flags &= ~TCB_INSYSCALL; 1434 get_scno(tcp); 1435 if (known_scno(tcp) == SYS_execve) 1436 break; 1437 } 1438 /* Set it running: maybe execve will be next. */ 1439#ifndef FREEBSD 1440 arg = 0; 1441 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1442#else /* FREEBSD */ 1443 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1444#endif /* FREEBSD */ 1445 perror("PIOCRUN"); 1446 return -1; 1447 } 1448#ifdef FREEBSD 1449 /* handle the case where we "opened" the child before 1450 it did the kill -STOP */ 1451 if (tcp->status.PR_WHY == PR_SIGNALLED && 1452 tcp->status.PR_WHAT == SIGSTOP) 1453 kill(tcp->pid, SIGCONT); 1454#endif 1455 } 1456#ifndef FREEBSD 1457 } 1458#else /* FREEBSD */ 1459 } else { 1460 if (attaching < 2) { 1461 /* We are attaching to an already running process. 1462 * Try to figure out the state of the process in syscalls, 1463 * to handle the first event well. 1464 * This is done by having a look at the "wchan" property of the 1465 * process, which tells where it is stopped (if it is). */ 1466 FILE * status; 1467 char wchan[20]; /* should be enough */ 1468 1469 sprintf(proc, "/proc/%d/status", tcp->pid); 1470 status = fopen(proc, "r"); 1471 if (status && 1472 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 1473 "%*d,%*d %*d,%*d %19s", wchan) == 1) && 1474 strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 1475 strcmp(wchan, "stopevent")) { 1476 /* The process is asleep in the middle of a syscall. 1477 Fake the syscall entry event */ 1478 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 1479 tcp->status.PR_WHY = PR_SYSENTRY; 1480 trace_syscall(tcp); 1481 } 1482 if (status) 1483 fclose(status); 1484 } /* otherwise it's a fork being followed */ 1485 } 1486#endif /* FREEBSD */ 1487#ifndef HAVE_POLLABLE_PROCFS 1488 if (proc_poll_pipe[0] != -1) 1489 proc_poller(tcp->pfd); 1490 else if (nprocs > 1) { 1491 proc_poll_open(); 1492 proc_poller(last_pfd); 1493 proc_poller(tcp->pfd); 1494 } 1495 last_pfd = tcp->pfd; 1496#endif /* !HAVE_POLLABLE_PROCFS */ 1497 return 0; 1498} 1499 1500#endif /* USE_PROCFS */ 1501 1502struct tcb * 1503pid2tcb(int pid) 1504{ 1505 int i; 1506 1507 if (pid <= 0) 1508 return NULL; 1509 1510 for (i = 0; i < tcbtabsize; i++) { 1511 struct tcb *tcp = tcbtab[i]; 1512 if (tcp->pid == pid && (tcp->flags & TCB_INUSE)) 1513 return tcp; 1514 } 1515 1516 return NULL; 1517} 1518 1519#ifdef USE_PROCFS 1520 1521static struct tcb * 1522first_used_tcb(void) 1523{ 1524 int i; 1525 struct tcb *tcp; 1526 for (i = 0; i < tcbtabsize; i++) { 1527 tcp = tcbtab[i]; 1528 if (tcp->flags & TCB_INUSE) 1529 return tcp; 1530 } 1531 return NULL; 1532} 1533 1534static struct tcb * 1535pfd2tcb(int pfd) 1536{ 1537 int i; 1538 1539 for (i = 0; i < tcbtabsize; i++) { 1540 struct tcb *tcp = tcbtab[i]; 1541 if (tcp->pfd != pfd) 1542 continue; 1543 if (tcp->flags & TCB_INUSE) 1544 return tcp; 1545 } 1546 return NULL; 1547} 1548 1549#endif /* USE_PROCFS */ 1550 1551void 1552droptcb(struct tcb *tcp) 1553{ 1554 if (tcp->pid == 0) 1555 return; 1556#ifdef TCB_CLONE_THREAD 1557 if (tcp->nclone_threads > 0) { 1558 /* There are other threads left in this process, but this 1559 is the one whose PID represents the whole process. 1560 We need to keep this record around as a zombie until 1561 all the threads die. */ 1562 tcp->flags |= TCB_EXITING; 1563 return; 1564 } 1565#endif 1566 nprocs--; 1567 if (debug) 1568 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs); 1569 tcp->pid = 0; 1570 1571 if (tcp->parent != NULL) { 1572#ifdef TCB_CLONE_THREAD 1573 if (tcp->flags & TCB_CLONE_THREAD) 1574 tcp->parent->nclone_threads--; 1575#endif 1576#ifdef LINUX 1577 /* Update fields like NCLONE_DETACHED, only 1578 for zombie group leader that has already reported 1579 and been short-circuited at the top of this 1580 function. The same condition as at the top of DETACH. */ 1581 if ((tcp->flags & TCB_CLONE_THREAD) && 1582 tcp->parent->nclone_threads == 0 && 1583 (tcp->parent->flags & TCB_EXITING)) 1584 droptcb(tcp->parent); 1585#endif 1586 tcp->parent = NULL; 1587 } 1588 1589 tcp->flags = 0; 1590 if (tcp->pfd != -1) { 1591 close(tcp->pfd); 1592 tcp->pfd = -1; 1593#ifdef FREEBSD 1594 if (tcp->pfd_reg != -1) { 1595 close(tcp->pfd_reg); 1596 tcp->pfd_reg = -1; 1597 } 1598 if (tcp->pfd_status != -1) { 1599 close(tcp->pfd_status); 1600 tcp->pfd_status = -1; 1601 } 1602#endif /* !FREEBSD */ 1603#ifdef USE_PROCFS 1604 rebuild_pollv(); /* Note, flags needs to be cleared by now. */ 1605#endif 1606 } 1607 1608 if (outfname && followfork > 1 && tcp->outf) 1609 fclose(tcp->outf); 1610 1611 tcp->outf = 0; 1612} 1613 1614/* detach traced process; continue with sig 1615 Never call DETACH twice on the same process as both unattached and 1616 attached-unstopped processes give the same ESRCH. For unattached process we 1617 would SIGSTOP it and wait for its SIGSTOP notification forever. */ 1618 1619static int 1620detach(struct tcb *tcp, int sig) 1621{ 1622 int error = 0; 1623#ifdef LINUX 1624 int status, catch_sigstop; 1625 struct tcb *zombie = NULL; 1626 1627 /* If the group leader is lingering only because of this other 1628 thread now dying, then detach the leader as well. */ 1629 if ((tcp->flags & TCB_CLONE_THREAD) && 1630 tcp->parent->nclone_threads == 1 && 1631 (tcp->parent->flags & TCB_EXITING)) 1632 zombie = tcp->parent; 1633#endif 1634 1635 if (tcp->flags & TCB_BPTSET) 1636 clearbpt(tcp); 1637 1638#ifdef LINUX 1639 /* 1640 * Linux wrongly insists the child be stopped 1641 * before detaching. Arghh. We go through hoops 1642 * to make a clean break of things. 1643 */ 1644#if defined(SPARC) 1645#undef PTRACE_DETACH 1646#define PTRACE_DETACH PTRACE_SUNDETACH 1647#endif 1648 /* 1649 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the 1650 * expected SIGSTOP. We must catch exactly one as otherwise the 1651 * detached process would be left stopped (process state T). 1652 */ 1653 catch_sigstop = (tcp->flags & TCB_STARTUP); 1654 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 1655 /* On a clear day, you can see forever. */ 1656 } 1657 else if (errno != ESRCH) { 1658 /* Shouldn't happen. */ 1659 perror("detach: ptrace(PTRACE_DETACH, ...)"); 1660 } 1661 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid 1662 : tcp->pid), 1663 tcp->pid, 0) < 0) { 1664 if (errno != ESRCH) 1665 perror("detach: checking sanity"); 1666 } 1667 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD 1668 ? tcp->parent->pid : tcp->pid), 1669 tcp->pid, SIGSTOP) < 0) { 1670 if (errno != ESRCH) 1671 perror("detach: stopping child"); 1672 } 1673 else 1674 catch_sigstop = 1; 1675 if (catch_sigstop) { 1676 for (;;) { 1677#ifdef __WALL 1678 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 1679 if (errno == ECHILD) /* Already gone. */ 1680 break; 1681 if (errno != EINVAL) { 1682 perror("detach: waiting"); 1683 break; 1684 } 1685#endif /* __WALL */ 1686 /* No __WALL here. */ 1687 if (waitpid(tcp->pid, &status, 0) < 0) { 1688 if (errno != ECHILD) { 1689 perror("detach: waiting"); 1690 break; 1691 } 1692#ifdef __WCLONE 1693 /* If no processes, try clones. */ 1694 if (wait4(tcp->pid, &status, __WCLONE, 1695 NULL) < 0) { 1696 if (errno != ECHILD) 1697 perror("detach: waiting"); 1698 break; 1699 } 1700#endif /* __WCLONE */ 1701 } 1702#ifdef __WALL 1703 } 1704#endif 1705 if (!WIFSTOPPED(status)) { 1706 /* Au revoir, mon ami. */ 1707 break; 1708 } 1709 if (WSTOPSIG(status) == SIGSTOP) { 1710 ptrace_restart(PTRACE_DETACH, tcp, sig); 1711 break; 1712 } 1713 error = ptrace_restart(PTRACE_CONT, tcp, 1714 WSTOPSIG(status) == syscall_trap_sig ? 0 1715 : WSTOPSIG(status)); 1716 if (error < 0) 1717 break; 1718 } 1719 } 1720#endif /* LINUX */ 1721 1722#if defined(SUNOS4) 1723 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 1724 if (sig && kill(tcp->pid, sig) < 0) 1725 perror("detach: kill"); 1726 sig = 0; 1727 error = ptrace_restart(PTRACE_DETACH, tcp, sig); 1728#endif /* SUNOS4 */ 1729 1730 if (!qflag) 1731 fprintf(stderr, "Process %u detached\n", tcp->pid); 1732 1733 droptcb(tcp); 1734 1735#ifdef LINUX 1736 if (zombie != NULL) { 1737 /* TCP no longer exists therefore you must not detach() it. */ 1738 droptcb(zombie); 1739 } 1740#endif 1741 1742 return error; 1743} 1744 1745#ifdef USE_PROCFS 1746 1747static void reaper(int sig) 1748{ 1749 int pid; 1750 int status; 1751 1752 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 1753 } 1754} 1755 1756#endif /* USE_PROCFS */ 1757 1758static void 1759cleanup(void) 1760{ 1761 int i; 1762 struct tcb *tcp; 1763 1764 for (i = 0; i < tcbtabsize; i++) { 1765 tcp = tcbtab[i]; 1766 if (!(tcp->flags & TCB_INUSE)) 1767 continue; 1768 if (debug) 1769 fprintf(stderr, 1770 "cleanup: looking at pid %u\n", tcp->pid); 1771 if (tcp_last && 1772 (!outfname || followfork < 2 || tcp_last == tcp)) { 1773 tprintf(" <unfinished ...>"); 1774 printtrailer(); 1775 } 1776 if (tcp->flags & TCB_ATTACHED) 1777 detach(tcp, 0); 1778 else { 1779 kill(tcp->pid, SIGCONT); 1780 kill(tcp->pid, SIGTERM); 1781 } 1782 } 1783 if (cflag) 1784 call_summary(outf); 1785} 1786 1787static void 1788interrupt(int sig) 1789{ 1790 interrupted = 1; 1791} 1792 1793#ifndef HAVE_STRERROR 1794 1795#if !HAVE_DECL_SYS_ERRLIST 1796extern int sys_nerr; 1797extern char *sys_errlist[]; 1798#endif /* HAVE_DECL_SYS_ERRLIST */ 1799 1800const char * 1801strerror(int err_no) 1802{ 1803 static char buf[64]; 1804 1805 if (err_no < 1 || err_no >= sys_nerr) { 1806 sprintf(buf, "Unknown error %d", err_no); 1807 return buf; 1808 } 1809 return sys_errlist[err_no]; 1810} 1811 1812#endif /* HAVE_STERRROR */ 1813 1814#ifndef HAVE_STRSIGNAL 1815 1816#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 1817extern char *sys_siglist[]; 1818#endif 1819#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 1820extern char *_sys_siglist[]; 1821#endif 1822 1823const char * 1824strsignal(int sig) 1825{ 1826 static char buf[64]; 1827 1828 if (sig < 1 || sig >= NSIG) { 1829 sprintf(buf, "Unknown signal %d", sig); 1830 return buf; 1831 } 1832#ifdef HAVE__SYS_SIGLIST 1833 return _sys_siglist[sig]; 1834#else 1835 return sys_siglist[sig]; 1836#endif 1837} 1838 1839#endif /* HAVE_STRSIGNAL */ 1840 1841#ifdef USE_PROCFS 1842 1843static void 1844rebuild_pollv(void) 1845{ 1846 int i, j; 1847 1848 if (pollv != NULL) 1849 free(pollv); 1850 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1851 if (pollv == NULL) { 1852 error_msg_and_die("Out of memory"); 1853 } 1854 1855 for (i = j = 0; i < tcbtabsize; i++) { 1856 struct tcb *tcp = tcbtab[i]; 1857 if (!(tcp->flags & TCB_INUSE)) 1858 continue; 1859 pollv[j].fd = tcp->pfd; 1860 pollv[j].events = POLLWANT; 1861 j++; 1862 } 1863 if (j != nprocs) { 1864 error_msg_and_die("proc miscount"); 1865 } 1866} 1867 1868#ifndef HAVE_POLLABLE_PROCFS 1869 1870static void 1871proc_poll_open(void) 1872{ 1873 int i; 1874 1875 if (pipe(proc_poll_pipe) < 0) { 1876 perror_msg_and_die("pipe"); 1877 } 1878 for (i = 0; i < 2; i++) { 1879 set_cloexec_flag(proc_poll_pipe[i]); 1880 } 1881} 1882 1883static int 1884proc_poll(struct pollfd *pollv, int nfds, int timeout) 1885{ 1886 int i; 1887 int n; 1888 struct proc_pollfd pollinfo; 1889 1890 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 1891 return n; 1892 if (n != sizeof(struct proc_pollfd)) { 1893 error_msg_and_die("panic: short read: %d", n); 1894 } 1895 for (i = 0; i < nprocs; i++) { 1896 if (pollv[i].fd == pollinfo.fd) 1897 pollv[i].revents = pollinfo.revents; 1898 else 1899 pollv[i].revents = 0; 1900 } 1901 poller_pid = pollinfo.pid; 1902 return 1; 1903} 1904 1905static void 1906wakeup_handler(int sig) 1907{ 1908} 1909 1910static void 1911proc_poller(int pfd) 1912{ 1913 struct proc_pollfd pollinfo; 1914 struct sigaction sa; 1915 sigset_t blocked_set, empty_set; 1916 int i; 1917 int n; 1918 struct rlimit rl; 1919#ifdef FREEBSD 1920 struct procfs_status pfs; 1921#endif /* FREEBSD */ 1922 1923 switch (fork()) { 1924 case -1: 1925 perror_msg_and_die("fork"); 1926 case 0: 1927 break; 1928 default: 1929 return; 1930 } 1931 1932 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 1933 sa.sa_flags = 0; 1934 sigemptyset(&sa.sa_mask); 1935 sigaction(SIGHUP, &sa, NULL); 1936 sigaction(SIGINT, &sa, NULL); 1937 sigaction(SIGQUIT, &sa, NULL); 1938 sigaction(SIGPIPE, &sa, NULL); 1939 sigaction(SIGTERM, &sa, NULL); 1940 sa.sa_handler = wakeup_handler; 1941 sigaction(SIGUSR1, &sa, NULL); 1942 sigemptyset(&blocked_set); 1943 sigaddset(&blocked_set, SIGUSR1); 1944 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 1945 sigemptyset(&empty_set); 1946 1947 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1948 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)"); 1949 } 1950 n = rl.rlim_cur; 1951 for (i = 0; i < n; i++) { 1952 if (i != pfd && i != proc_poll_pipe[1]) 1953 close(i); 1954 } 1955 1956 pollinfo.fd = pfd; 1957 pollinfo.pid = getpid(); 1958 for (;;) { 1959#ifndef FREEBSD 1960 if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 1961#else 1962 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 1963#endif 1964 { 1965 switch (errno) { 1966 case EINTR: 1967 continue; 1968 case EBADF: 1969 pollinfo.revents = POLLERR; 1970 break; 1971 case ENOENT: 1972 pollinfo.revents = POLLHUP; 1973 break; 1974 default: 1975 perror("proc_poller: PIOCWSTOP"); 1976 } 1977 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 1978 _exit(0); 1979 } 1980 pollinfo.revents = POLLWANT; 1981 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 1982 sigsuspend(&empty_set); 1983 } 1984} 1985 1986#endif /* !HAVE_POLLABLE_PROCFS */ 1987 1988static int 1989choose_pfd() 1990{ 1991 int i, j; 1992 struct tcb *tcp; 1993 1994 static int last; 1995 1996 if (followfork < 2 && 1997 last < nprocs && (pollv[last].revents & POLLWANT)) { 1998 /* 1999 * The previous process is ready to run again. We'll 2000 * let it do so if it is currently in a syscall. This 2001 * heuristic improves the readability of the trace. 2002 */ 2003 tcp = pfd2tcb(pollv[last].fd); 2004 if (tcp && (tcp->flags & TCB_INSYSCALL)) 2005 return pollv[last].fd; 2006 } 2007 2008 for (i = 0; i < nprocs; i++) { 2009 /* Let competing children run round robin. */ 2010 j = (i + last + 1) % nprocs; 2011 if (pollv[j].revents & (POLLHUP | POLLERR)) { 2012 tcp = pfd2tcb(pollv[j].fd); 2013 if (!tcp) { 2014 error_msg_and_die("lost proc"); 2015 } 2016 droptcb(tcp); 2017 return -1; 2018 } 2019 if (pollv[j].revents & POLLWANT) { 2020 last = j; 2021 return pollv[j].fd; 2022 } 2023 } 2024 error_msg_and_die("nothing ready"); 2025} 2026 2027static int 2028trace(void) 2029{ 2030#ifdef POLL_HACK 2031 struct tcb *in_syscall = NULL; 2032#endif 2033 struct tcb *tcp; 2034 int pfd; 2035 int what; 2036 int ioctl_result = 0, ioctl_errno = 0; 2037 long arg; 2038 2039 for (;;) { 2040 if (interactive) 2041 sigprocmask(SIG_SETMASK, &empty_set, NULL); 2042 2043 if (nprocs == 0) 2044 break; 2045 2046 switch (nprocs) { 2047 case 1: 2048#ifndef HAVE_POLLABLE_PROCFS 2049 if (proc_poll_pipe[0] == -1) { 2050#endif 2051 tcp = first_used_tcb(); 2052 if (!tcp) 2053 continue; 2054 pfd = tcp->pfd; 2055 if (pfd == -1) 2056 continue; 2057 break; 2058#ifndef HAVE_POLLABLE_PROCFS 2059 } 2060 /* fall through ... */ 2061#endif /* !HAVE_POLLABLE_PROCFS */ 2062 default: 2063#ifdef HAVE_POLLABLE_PROCFS 2064#ifdef POLL_HACK 2065 /* On some systems (e.g. UnixWare) we get too much ugly 2066 "unfinished..." stuff when multiple proceses are in 2067 syscalls. Here's a nasty hack */ 2068 2069 if (in_syscall) { 2070 struct pollfd pv; 2071 tcp = in_syscall; 2072 in_syscall = NULL; 2073 pv.fd = tcp->pfd; 2074 pv.events = POLLWANT; 2075 if ((what = poll(&pv, 1, 1)) < 0) { 2076 if (interrupted) 2077 return 0; 2078 continue; 2079 } 2080 else if (what == 1 && pv.revents & POLLWANT) { 2081 goto FOUND; 2082 } 2083 } 2084#endif 2085 2086 if (poll(pollv, nprocs, INFTIM) < 0) { 2087 if (interrupted) 2088 return 0; 2089 continue; 2090 } 2091#else /* !HAVE_POLLABLE_PROCFS */ 2092 if (proc_poll(pollv, nprocs, INFTIM) < 0) { 2093 if (interrupted) 2094 return 0; 2095 continue; 2096 } 2097#endif /* !HAVE_POLLABLE_PROCFS */ 2098 pfd = choose_pfd(); 2099 if (pfd == -1) 2100 continue; 2101 break; 2102 } 2103 2104 /* Look up `pfd' in our table. */ 2105 if ((tcp = pfd2tcb(pfd)) == NULL) { 2106 error_msg_and_die("unknown pfd: %u", pfd); 2107 } 2108#ifdef POLL_HACK 2109 FOUND: 2110#endif 2111 /* Get the status of the process. */ 2112 if (!interrupted) { 2113#ifndef FREEBSD 2114 ioctl_result = IOCTL_WSTOP(tcp); 2115#else /* FREEBSD */ 2116 /* Thanks to some scheduling mystery, the first poller 2117 sometimes waits for the already processed end of fork 2118 event. Doing a non blocking poll here solves the problem. */ 2119 if (proc_poll_pipe[0] != -1) 2120 ioctl_result = IOCTL_STATUS(tcp); 2121 else 2122 ioctl_result = IOCTL_WSTOP(tcp); 2123#endif /* FREEBSD */ 2124 ioctl_errno = errno; 2125#ifndef HAVE_POLLABLE_PROCFS 2126 if (proc_poll_pipe[0] != -1) { 2127 if (ioctl_result < 0) 2128 kill(poller_pid, SIGKILL); 2129 else 2130 kill(poller_pid, SIGUSR1); 2131 } 2132#endif /* !HAVE_POLLABLE_PROCFS */ 2133 } 2134 if (interrupted) 2135 return 0; 2136 2137 if (interactive) 2138 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 2139 2140 if (ioctl_result < 0) { 2141 /* Find out what happened if it failed. */ 2142 switch (ioctl_errno) { 2143 case EINTR: 2144 case EBADF: 2145 continue; 2146#ifdef FREEBSD 2147 case ENOTTY: 2148#endif 2149 case ENOENT: 2150 droptcb(tcp); 2151 continue; 2152 default: 2153 perror_msg_and_die("PIOCWSTOP"); 2154 } 2155 } 2156 2157#ifdef FREEBSD 2158 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 2159 /* discard first event for a syscall we never entered */ 2160 IOCTL(tcp->pfd, PIOCRUN, 0); 2161 continue; 2162 } 2163#endif 2164 2165 /* clear the just started flag */ 2166 tcp->flags &= ~TCB_STARTUP; 2167 2168 /* set current output file */ 2169 outf = tcp->outf; 2170 curcol = tcp->curcol; 2171 2172 if (cflag) { 2173 struct timeval stime; 2174#ifdef FREEBSD 2175 char buf[1024]; 2176 int len; 2177 2178 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 2179 buf[len] = '\0'; 2180 sscanf(buf, 2181 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 2182 &stime.tv_sec, &stime.tv_usec); 2183 } else 2184 stime.tv_sec = stime.tv_usec = 0; 2185#else /* !FREEBSD */ 2186 stime.tv_sec = tcp->status.pr_stime.tv_sec; 2187 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 2188#endif /* !FREEBSD */ 2189 tv_sub(&tcp->dtime, &stime, &tcp->stime); 2190 tcp->stime = stime; 2191 } 2192 what = tcp->status.PR_WHAT; 2193 switch (tcp->status.PR_WHY) { 2194#ifndef FREEBSD 2195 case PR_REQUESTED: 2196 if (tcp->status.PR_FLAGS & PR_ASLEEP) { 2197 tcp->status.PR_WHY = PR_SYSENTRY; 2198 if (trace_syscall(tcp) < 0) { 2199 error_msg_and_die("syscall trouble"); 2200 } 2201 } 2202 break; 2203#endif /* !FREEBSD */ 2204 case PR_SYSENTRY: 2205#ifdef POLL_HACK 2206 in_syscall = tcp; 2207#endif 2208 case PR_SYSEXIT: 2209 if (trace_syscall(tcp) < 0) { 2210 error_msg_and_die("syscall trouble"); 2211 } 2212 break; 2213 case PR_SIGNALLED: 2214 if (cflag != CFLAG_ONLY_STATS 2215 && (qual_flags[what] & QUAL_SIGNAL)) { 2216 printleader(tcp); 2217 tprintf("--- %s (%s) ---", 2218 signame(what), strsignal(what)); 2219 printtrailer(); 2220#ifdef PR_INFO 2221 if (tcp->status.PR_INFO.si_signo == what) { 2222 printleader(tcp); 2223 tprintf(" siginfo="); 2224 printsiginfo(&tcp->status.PR_INFO, 1); 2225 printtrailer(); 2226 } 2227#endif 2228 } 2229 break; 2230 case PR_FAULTED: 2231 if (cflag != CFLAGS_ONLY_STATS 2232 && (qual_flags[what] & QUAL_FAULT)) { 2233 printleader(tcp); 2234 tprintf("=== FAULT %d ===", what); 2235 printtrailer(); 2236 } 2237 break; 2238#ifdef FREEBSD 2239 case 0: /* handle case we polled for nothing */ 2240 continue; 2241#endif 2242 default: 2243 error_msg_and_die("odd stop %d", tcp->status.PR_WHY); 2244 break; 2245 } 2246 /* Remember current print column before continuing. */ 2247 tcp->curcol = curcol; 2248 arg = 0; 2249#ifndef FREEBSD 2250 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) 2251#else 2252 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) 2253#endif 2254 { 2255 perror_msg_and_die("PIOCRUN"); 2256 } 2257 } 2258 return 0; 2259} 2260 2261#else /* !USE_PROCFS */ 2262 2263#ifdef TCB_GROUP_EXITING 2264/* Handle an exit detach or death signal that is taking all the 2265 related clone threads with it. This is called in three circumstances: 2266 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent). 2267 SIG == 0 Continuing TCP will perform an exit_group syscall. 2268 SIG == other Continuing TCP with SIG will kill the process. 2269*/ 2270static int 2271handle_group_exit(struct tcb *tcp, int sig) 2272{ 2273 /* We need to locate our records of all the clone threads 2274 related to TCP, either its children or siblings. */ 2275 struct tcb *leader = NULL; 2276 2277 if (tcp->flags & TCB_CLONE_THREAD) 2278 leader = tcp->parent; 2279 2280 if (sig < 0) { 2281 if (leader != NULL && leader != tcp 2282 && !(leader->flags & TCB_GROUP_EXITING) 2283 && !(tcp->flags & TCB_STARTUP) 2284 ) { 2285 fprintf(stderr, 2286 "PANIC: handle_group_exit: %d leader %d\n", 2287 tcp->pid, leader ? leader->pid : -1); 2288 } 2289 /* TCP no longer exists therefore you must not detach() it. */ 2290 droptcb(tcp); /* Already died. */ 2291 } 2292 else { 2293 /* Mark that we are taking the process down. */ 2294 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING; 2295 if (tcp->flags & TCB_ATTACHED) { 2296 detach(tcp, sig); 2297 if (leader != NULL && leader != tcp) 2298 leader->flags |= TCB_GROUP_EXITING; 2299 } else { 2300 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) { 2301 cleanup(); 2302 return -1; 2303 } 2304 if (leader != NULL) { 2305 leader->flags |= TCB_GROUP_EXITING; 2306 if (leader != tcp) 2307 droptcb(tcp); 2308 } 2309 /* The leader will report to us as parent now, 2310 and then we'll get to the SIG==-1 case. */ 2311 return 0; 2312 } 2313 } 2314 2315 return 0; 2316} 2317#endif 2318 2319#ifdef LINUX 2320static int 2321handle_ptrace_event(int status, struct tcb *tcp) 2322{ 2323 if (status >> 16 == PTRACE_EVENT_VFORK || 2324 status >> 16 == PTRACE_EVENT_CLONE || 2325 status >> 16 == PTRACE_EVENT_FORK) { 2326 long childpid; 2327 2328 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) { 2329 if (errno != ESRCH) { 2330 error_msg_and_die("Cannot get new child's pid"); 2331 } 2332 return -1; 2333 } 2334 return handle_new_child(tcp, childpid, 0); 2335 } 2336 if (status >> 16 == PTRACE_EVENT_EXEC) { 2337 return 0; 2338 } 2339 /* Some PTRACE_EVENT_foo we didn't ask for?! */ 2340 error_msg("Unexpected status %x on pid %d", status, tcp->pid); 2341 return 1; 2342} 2343#endif 2344 2345static int 2346trace() 2347{ 2348 int pid; 2349 int wait_errno; 2350 int status; 2351 struct tcb *tcp; 2352#ifdef LINUX 2353 struct rusage ru; 2354#ifdef __WALL 2355 static int wait4_options = __WALL; 2356#endif 2357#endif /* LINUX */ 2358 2359 while (nprocs != 0) { 2360 if (interrupted) 2361 return 0; 2362 if (interactive) 2363 sigprocmask(SIG_SETMASK, &empty_set, NULL); 2364#ifdef LINUX 2365#ifdef __WALL 2366 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL); 2367 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 2368 /* this kernel does not support __WALL */ 2369 wait4_options &= ~__WALL; 2370 errno = 0; 2371 pid = wait4(-1, &status, wait4_options, 2372 cflag ? &ru : NULL); 2373 } 2374 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 2375 /* most likely a "cloned" process */ 2376 pid = wait4(-1, &status, __WCLONE, 2377 cflag ? &ru : NULL); 2378 if (pid == -1) { 2379 perror_msg("wait4(__WCLONE) failed"); 2380 } 2381 } 2382#else 2383 pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 2384#endif /* __WALL */ 2385#endif /* LINUX */ 2386#ifdef SUNOS4 2387 pid = wait(&status); 2388#endif /* SUNOS4 */ 2389 wait_errno = errno; 2390 if (interactive) 2391 sigprocmask(SIG_BLOCK, &blocked_set, NULL); 2392 2393 if (pid == -1) { 2394 switch (wait_errno) { 2395 case EINTR: 2396 continue; 2397 case ECHILD: 2398 /* 2399 * We would like to verify this case 2400 * but sometimes a race in Solbourne's 2401 * version of SunOS sometimes reports 2402 * ECHILD before sending us SIGCHILD. 2403 */ 2404 return 0; 2405 default: 2406 errno = wait_errno; 2407 perror("strace: wait"); 2408 return -1; 2409 } 2410 } 2411 if (pid == popen_pid) { 2412 if (WIFEXITED(status) || WIFSIGNALED(status)) 2413 popen_pid = 0; 2414 continue; 2415 } 2416 if (debug) { 2417 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16]; 2418#ifdef LINUX 2419 unsigned ev = (unsigned)status >> 16; 2420 if (ev) { 2421 static const char *const event_names[] = { 2422 [PTRACE_EVENT_CLONE] = "CLONE", 2423 [PTRACE_EVENT_FORK] = "FORK", 2424 [PTRACE_EVENT_VFORK] = "VFORK", 2425 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE", 2426 [PTRACE_EVENT_EXEC] = "EXEC", 2427 [PTRACE_EVENT_EXIT] = "EXIT", 2428 }; 2429 const char *e; 2430 if (ev < ARRAY_SIZE(event_names)) 2431 e = event_names[ev]; 2432 else { 2433 sprintf(buf, "?? (%u)", ev); 2434 e = buf; 2435 } 2436 fprintf(stderr, " PTRACE_EVENT_%s", e); 2437 } 2438#endif 2439 strcpy(buf, "???"); 2440 if (WIFSIGNALED(status)) 2441#ifdef WCOREDUMP 2442 sprintf(buf, "WIFSIGNALED,%ssig=%s", 2443 WCOREDUMP(status) ? "core," : "", 2444 signame(WTERMSIG(status))); 2445#else 2446 sprintf(buf, "WIFSIGNALED,sig=%s", 2447 signame(WTERMSIG(status))); 2448#endif 2449 if (WIFEXITED(status)) 2450 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status)); 2451 if (WIFSTOPPED(status)) 2452 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status))); 2453 if (WIFCONTINUED(status)) 2454 strcpy(buf, "WIFCONTINUED"); 2455 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf); 2456 } 2457 2458 /* Look up `pid' in our table. */ 2459 if ((tcp = pid2tcb(pid)) == NULL) { 2460#ifdef LINUX 2461 if (followfork) { 2462 /* This is needed to go with the CLONE_PTRACE 2463 changes in process.c/util.c: we might see 2464 the child's initial trap before we see the 2465 parent return from the clone syscall. 2466 Leave the child suspended until the parent 2467 returns from its system call. Only then 2468 will we have the association of parent and 2469 child so that we know how to do clearbpt 2470 in the child. */ 2471 tcp = alloctcb(pid); 2472 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED; 2473 if (!qflag) 2474 fprintf(stderr, "\ 2475Process %d attached (waiting for parent)\n", 2476 pid); 2477 } 2478 else 2479 /* This can happen if a clone call used 2480 CLONE_PTRACE itself. */ 2481#endif 2482 { 2483 if (WIFSTOPPED(status)) 2484 ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2485 error_msg_and_die("Unknown pid: %u", pid); 2486 } 2487 } 2488 /* set current output file */ 2489 outf = tcp->outf; 2490 curcol = tcp->curcol; 2491 if (cflag) { 2492#ifdef LINUX 2493 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 2494 tcp->stime = ru.ru_stime; 2495#endif /* !LINUX */ 2496 } 2497 2498 if (tcp->flags & TCB_SUSPENDED) { 2499 /* 2500 * Apparently, doing any ptrace() call on a stopped 2501 * process, provokes the kernel to report the process 2502 * status again on a subsequent wait(), even if the 2503 * process has not been actually restarted. 2504 * Since we have inspected the arguments of suspended 2505 * processes we end up here testing for this case. 2506 */ 2507 continue; 2508 } 2509 if (WIFSIGNALED(status)) { 2510 if (pid == strace_child) 2511 exit_code = 0x100 | WTERMSIG(status); 2512 if (cflag != CFLAG_ONLY_STATS 2513 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 2514 printleader(tcp); 2515 tprintf("+++ killed by %s %s+++", 2516 signame(WTERMSIG(status)), 2517#ifdef WCOREDUMP 2518 WCOREDUMP(status) ? "(core dumped) " : 2519#endif 2520 ""); 2521 printtrailer(); 2522 } 2523#ifdef TCB_GROUP_EXITING 2524 handle_group_exit(tcp, -1); 2525#else 2526 droptcb(tcp); 2527#endif 2528 continue; 2529 } 2530 if (WIFEXITED(status)) { 2531 if (pid == strace_child) 2532 exit_code = WEXITSTATUS(status); 2533 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED 2534#ifdef TCB_GROUP_EXITING 2535 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING)) 2536 && !(tcp->flags & TCB_GROUP_EXITING) 2537#endif 2538 ) { 2539 fprintf(stderr, 2540 "PANIC: attached pid %u exited with %d\n", 2541 pid, WEXITSTATUS(status)); 2542 } 2543 if (tcp == tcp_last) { 2544 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL) 2545 tprintf(" <unfinished ... exit status %d>\n", 2546 WEXITSTATUS(status)); 2547 tcp_last = NULL; 2548 } 2549#ifdef TCB_GROUP_EXITING 2550 handle_group_exit(tcp, -1); 2551#else 2552 droptcb(tcp); 2553#endif 2554 continue; 2555 } 2556 if (!WIFSTOPPED(status)) { 2557 fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 2558 droptcb(tcp); 2559 continue; 2560 } 2561 2562 if (status >> 16) { 2563 if (handle_ptrace_event(status, tcp) != 1) 2564 goto tracing; 2565 } 2566 2567 /* 2568 * Interestingly, the process may stop 2569 * with STOPSIG equal to some other signal 2570 * than SIGSTOP if we happend to attach 2571 * just before the process takes a signal. 2572 * A no-MMU vforked child won't send up a signal, 2573 * so skip the first (lost) execve notification. 2574 */ 2575 if ((tcp->flags & TCB_STARTUP) && 2576 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) { 2577 /* 2578 * This flag is there to keep us in sync. 2579 * Next time this process stops it should 2580 * really be entering a system call. 2581 */ 2582 tcp->flags &= ~TCB_STARTUP; 2583 if (tcp->flags & TCB_BPTSET) { 2584 /* 2585 * One example is a breakpoint inherited from 2586 * parent through fork (). 2587 */ 2588 if (clearbpt(tcp) < 0) /* Pretty fatal */ { 2589 droptcb(tcp); 2590 cleanup(); 2591 return -1; 2592 } 2593 } 2594#ifdef LINUX 2595 /* If options were not set for this tracee yet */ 2596 if (tcp->parent == NULL) { 2597 if (ptrace_setoptions) { 2598 if (debug) 2599 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid); 2600 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) { 2601 if (errno != ESRCH) { 2602 /* Should never happen, really */ 2603 perror_msg_and_die("PTRACE_SETOPTIONS"); 2604 } 2605 } 2606 } 2607 } 2608#endif 2609 goto tracing; 2610 } 2611 2612 if (WSTOPSIG(status) != syscall_trap_sig) { 2613 if (WSTOPSIG(status) == SIGSTOP && 2614 (tcp->flags & TCB_SIGTRAPPED)) { 2615 /* 2616 * Trapped attempt to block SIGTRAP 2617 * Hope we are back in control now. 2618 */ 2619 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 2620 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 2621 cleanup(); 2622 return -1; 2623 } 2624 continue; 2625 } 2626 if (cflag != CFLAG_ONLY_STATS 2627 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 2628 siginfo_t si; 2629#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) 2630 long pc = 0; 2631 long psr = 0; 2632 2633 upeek(tcp, PT_CR_IPSR, &psr); 2634 upeek(tcp, PT_CR_IIP, &pc); 2635 2636# define PSR_RI 41 2637 pc += (psr >> PSR_RI) & 0x3; 2638# define PC_FORMAT_STR " @ %lx" 2639# define PC_FORMAT_ARG pc 2640#else 2641# define PC_FORMAT_STR "%s" 2642# define PC_FORMAT_ARG "" 2643#endif 2644 printleader(tcp); 2645 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { 2646 tprintf("--- "); 2647 printsiginfo(&si, verbose(tcp)); 2648 tprintf(" (%s)" PC_FORMAT_STR " ---", 2649 strsignal(WSTOPSIG(status)), 2650 PC_FORMAT_ARG); 2651 } else 2652 tprintf("--- %s by %s" PC_FORMAT_STR " ---", 2653 strsignal(WSTOPSIG(status)), 2654 signame(WSTOPSIG(status)), 2655 PC_FORMAT_ARG); 2656 printtrailer(); 2657 } 2658 if (((tcp->flags & TCB_ATTACHED) || 2659 tcp->nclone_threads > 0) && 2660 !sigishandled(tcp, WSTOPSIG(status))) { 2661#ifdef TCB_GROUP_EXITING 2662 handle_group_exit(tcp, WSTOPSIG(status)); 2663#else 2664 detach(tcp, WSTOPSIG(status)); 2665#endif 2666 continue; 2667 } 2668 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) { 2669 cleanup(); 2670 return -1; 2671 } 2672 tcp->flags &= ~TCB_SUSPENDED; 2673 continue; 2674 } 2675 /* we handled the STATUS, we are permitted to interrupt now. */ 2676 if (interrupted) 2677 return 0; 2678 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) { 2679 /* ptrace() failed in trace_syscall() with ESRCH. 2680 * Likely a result of process disappearing mid-flight. 2681 * Observed case: exit_group() terminating 2682 * all processes in thread group. In this case, threads 2683 * "disappear" in an unpredictable moment without any 2684 * notification to strace via wait(). 2685 */ 2686 if (tcp->flags & TCB_ATTACHED) { 2687 if (tcp_last) { 2688 /* Do we have dangling line "syscall(param, param"? 2689 * Finish the line then. 2690 */ 2691 tcp_last->flags |= TCB_REPRINT; 2692 tprintf(" <unfinished ...>"); 2693 printtrailer(); 2694 } 2695 detach(tcp, 0); 2696 } else { 2697 ptrace(PTRACE_KILL, 2698 tcp->pid, (char *) 1, SIGTERM); 2699 droptcb(tcp); 2700 } 2701 continue; 2702 } 2703 if (tcp->flags & TCB_EXITING) { 2704#ifdef TCB_GROUP_EXITING 2705 if (tcp->flags & TCB_GROUP_EXITING) { 2706 if (handle_group_exit(tcp, 0) < 0) 2707 return -1; 2708 continue; 2709 } 2710#endif 2711 if (tcp->flags & TCB_ATTACHED) 2712 detach(tcp, 0); 2713 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) { 2714 cleanup(); 2715 return -1; 2716 } 2717 continue; 2718 } 2719 if (tcp->flags & TCB_SUSPENDED) { 2720 if (!qflag) 2721 fprintf(stderr, "Process %u suspended\n", pid); 2722 continue; 2723 } 2724 tracing: 2725 /* Remember current print column before continuing. */ 2726 tcp->curcol = curcol; 2727 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 2728 cleanup(); 2729 return -1; 2730 } 2731 } 2732 return 0; 2733} 2734 2735#endif /* !USE_PROCFS */ 2736 2737void 2738tprintf(const char *fmt, ...) 2739{ 2740 va_list args; 2741 2742 va_start(args, fmt); 2743 if (outf) { 2744 int n = vfprintf(outf, fmt, args); 2745 if (n < 0) { 2746 if (outf != stderr) 2747 perror(outfname == NULL 2748 ? "<writing to pipe>" : outfname); 2749 } else 2750 curcol += n; 2751 } 2752 va_end(args); 2753 return; 2754} 2755 2756void 2757printleader(struct tcb *tcp) 2758{ 2759 if (tcp_last) { 2760 if (tcp_last->ptrace_errno) { 2761 if (tcp_last->flags & TCB_INSYSCALL) { 2762 tprintf(" <unavailable>) "); 2763 tabto(acolumn); 2764 } 2765 tprintf("= ? <unavailable>\n"); 2766 tcp_last->ptrace_errno = 0; 2767 } else if (!outfname || followfork < 2 || tcp_last == tcp) { 2768 tcp_last->flags |= TCB_REPRINT; 2769 tprintf(" <unfinished ...>\n"); 2770 } 2771 } 2772 curcol = 0; 2773 if ((followfork == 1 || pflag_seen > 1) && outfname) 2774 tprintf("%-5d ", tcp->pid); 2775 else if (nprocs > 1 && !outfname) 2776 tprintf("[pid %5u] ", tcp->pid); 2777 if (tflag) { 2778 char str[sizeof("HH:MM:SS")]; 2779 struct timeval tv, dtv; 2780 static struct timeval otv; 2781 2782 gettimeofday(&tv, NULL); 2783 if (rflag) { 2784 if (otv.tv_sec == 0) 2785 otv = tv; 2786 tv_sub(&dtv, &tv, &otv); 2787 tprintf("%6ld.%06ld ", 2788 (long) dtv.tv_sec, (long) dtv.tv_usec); 2789 otv = tv; 2790 } 2791 else if (tflag > 2) { 2792 tprintf("%ld.%06ld ", 2793 (long) tv.tv_sec, (long) tv.tv_usec); 2794 } 2795 else { 2796 time_t local = tv.tv_sec; 2797 strftime(str, sizeof(str), "%T", localtime(&local)); 2798 if (tflag > 1) 2799 tprintf("%s.%06ld ", str, (long) tv.tv_usec); 2800 else 2801 tprintf("%s ", str); 2802 } 2803 } 2804 if (iflag) 2805 printcall(tcp); 2806} 2807 2808void 2809tabto(int col) 2810{ 2811 if (curcol < col) 2812 tprintf("%*s", col - curcol, ""); 2813} 2814 2815void 2816printtrailer(void) 2817{ 2818 tprintf("\n"); 2819 tcp_last = NULL; 2820} 2821 2822#ifdef HAVE_MP_PROCFS 2823 2824int 2825mp_ioctl(int fd, int cmd, void *arg, int size) 2826{ 2827 struct iovec iov[2]; 2828 int n = 1; 2829 2830 iov[0].iov_base = &cmd; 2831 iov[0].iov_len = sizeof cmd; 2832 if (arg) { 2833 ++n; 2834 iov[1].iov_base = arg; 2835 iov[1].iov_len = size; 2836 } 2837 2838 return writev(fd, iov, n); 2839} 2840 2841#endif 2842