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