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>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
35 #include <sys/types.h>
39 #include <sys/param.h>
41 #include <sys/resource.h>
48 #include <sys/utsname.h>
51 # include <asm/unistd.h>
52 # if defined __NR_tkill
53 # define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
55 /* kill() may choose arbitrarily the target task of the process group
56 while we later wait on a that specific TID. PID process waits become
57 TID task specific waits for a process under ptrace(2). */
58 # warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
59 # define my_tkill(tid, sig) kill((tid), (sig))
63 #if defined(IA64) && defined(LINUX)
64 # include <asm/ptrace_offsets.h>
72 #include <sys/stropts.h>
79 extern char **environ;
84 int debug = 0, followfork = 0;
85 unsigned int ptrace_setoptions = 0;
86 /* Which WSTOPSIG(status) value marks syscall traps? */
87 static unsigned int syscall_trap_sig = SIGTRAP;
88 int dtime = 0, xflag = 0, qflag = 0;
89 cflag_t cflag = CFLAG_NONE;
90 static int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
95 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
96 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
97 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
98 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
102 /* We play with signal mask only if this mode is active: */
103 #define interactive (opt_intr == INTR_WHILE_WAIT)
106 * daemonized_tracer supports -D option.
107 * With this option, strace forks twice.
108 * Unlike normal case, with -D *grandparent* process exec's,
109 * becoming a traced process. Child exits (this prevents traced process
110 * from having children it doesn't expect to have), and grandchild
111 * attaches to grandparent similarly to strace -p PID.
112 * This allows for more transparent interaction in cases
113 * when process and its parent are communicating via signals,
114 * wait() etc. Without -D, strace process gets lodged in between,
115 * disrupting parent<->child link.
117 static bool daemonized_tracer = 0;
120 static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
121 # define use_seize (post_attach_sigstop == 0)
123 # define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
127 /* Sometimes we want to print only succeeding syscalls. */
128 int not_failing_only = 0;
130 /* Show path associated with fd arguments */
131 int show_fd_path = 0;
133 /* are we filtering traces based on paths? */
134 int tracing_paths = 0;
136 static int exit_code = 0;
137 static int strace_child = 0;
138 static int strace_tracer_pid = 0;
140 static char *username = NULL;
141 static uid_t run_uid;
142 static gid_t run_gid;
144 int max_strlen = DEFAULT_STRLEN;
145 static int acolumn = DEFAULT_ACOLUMN;
146 static char *acolumn_spaces;
147 static char *outfname = NULL;
149 struct tcb *printing_tcp = NULL;
151 static struct tcb **tcbtab;
152 static unsigned int nprocs, tcbtabsize;
153 static const char *progname;
155 static char *os_release; /* from uname() */
157 static int detach(struct tcb *tcp);
158 static int trace(void);
159 static void cleanup(void);
160 static void interrupt(int sig);
161 static sigset_t empty_set, blocked_set;
163 #ifdef HAVE_SIG_ATOMIC_T
164 static volatile sig_atomic_t interrupted;
166 static volatile int interrupted;
171 static struct tcb *pfd2tcb(int pfd);
172 static void reaper(int sig);
173 static void rebuild_pollv(void);
174 static struct pollfd *pollv;
176 #ifndef HAVE_POLLABLE_PROCFS
178 static void proc_poll_open(void);
179 static void proc_poller(int pfd);
187 static int poller_pid;
188 static int proc_poll_pipe[2] = { -1, -1 };
190 #endif /* !HAVE_POLLABLE_PROCFS */
192 #ifdef HAVE_MP_PROCFS
193 #define POLLWANT POLLWRNORM
195 #define POLLWANT POLLPRI
197 #endif /* USE_PROCFS */
200 usage(FILE *ofp, int exitval)
203 usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
204 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
205 [-P path] [PROG [ARGS]]\n\
206 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
208 -c -- count time, calls, and errors for each syscall and report summary\n\
209 -C -- like -c but also print regular output while processes are running\n\
210 -D -- run tracer process as a detached grandchild, not as parent\n\
211 -f -- follow forks, -ff -- with output into separate files\n\
212 -F -- attempt to follow vforks\n\
213 -i -- print instruction pointer at time of syscall\n\
215 1: no signals are blocked\n\
216 2: fatal signals are blocked while decoding syscall (default)\n\
217 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
218 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
219 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
220 -q -- suppress messages about attaching, detaching, etc.\n\
221 -r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
222 -T -- print time spent in each syscall\n\
223 -v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
224 -x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
225 -y -- print paths associated with file descriptor arguments\n\
226 -h -- print help message\n\
227 -V -- print version\n\
228 -a column -- alignment COLUMN for printing syscall results (default %d)\n\
229 -e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
230 options: trace, abbrev, verbose, raw, signal, read, or write\n\
231 -o file -- send trace output to FILE instead of stderr\n\
232 -O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
233 -p pid -- trace process with process id PID, may be repeated\n\
234 -s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
235 -S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
236 -u username -- run command as username handling setuid and/or setgid\n\
237 -E var=val -- put var=val in the environment for command\n\
238 -E var -- remove var from the environment for command\n\
239 -P path -- trace accesses to path\n\
240 " /* this is broken, so don't document it
241 -z -- print only succeeding syscalls\n\
243 , DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
247 static void die(void) __attribute__ ((noreturn));
248 static void die(void)
250 if (strace_tracer_pid == getpid()) {
257 static void verror_msg(int err_no, const char *fmt, va_list p)
263 /* We want to print entire message with single fprintf to ensure
264 * message integrity if stderr is shared with other programs.
265 * Thus we use vasprintf + single fprintf.
268 if (vasprintf(&msg, fmt, p) >= 0) {
270 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
272 fprintf(stderr, "%s: %s\n", progname, msg);
275 /* malloc in vasprintf failed, try it without malloc */
276 fprintf(stderr, "%s: ", progname);
277 vfprintf(stderr, fmt, p);
279 fprintf(stderr, ": %s\n", strerror(err_no));
283 /* We don't switch stderr to buffered, thus fprintf(stderr)
284 * always flushes its output and this is not necessary: */
285 /* fflush(stderr); */
288 void error_msg(const char *fmt, ...)
292 verror_msg(0, fmt, p);
296 void error_msg_and_die(const char *fmt, ...)
300 verror_msg(0, fmt, p);
304 void perror_msg(const char *fmt, ...)
308 verror_msg(errno, fmt, p);
312 void perror_msg_and_die(const char *fmt, ...)
316 verror_msg(errno, fmt, p);
320 void die_out_of_memory(void)
322 static bool recursed = 0;
326 error_msg_and_die("Out of memory");
338 /* Glue for systems without a MMU that cannot provide fork() */
340 # define strace_vforked 0
342 # define strace_vforked 1
343 # define fork() vfork()
348 ptrace_attach_or_seize(int pid)
352 return ptrace(PTRACE_ATTACH, pid, 0, 0);
353 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
356 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
360 # define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
364 set_cloexec_flag(int fd)
368 flags = fcntl(fd, F_GETFD);
370 /* Can happen only if fd is bad.
371 * Should never happen: if it does, we have a bug
372 * in the caller. Therefore we just abort
373 * instead of propagating the error.
375 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
378 newflags = flags | FD_CLOEXEC;
379 if (flags == newflags)
382 fcntl(fd, F_SETFD, newflags); /* never fails */
386 * When strace is setuid executable, we have to swap uids
387 * before and after filesystem and process management operations.
393 int euid = geteuid(), uid = getuid();
395 if (euid != uid && setreuid(euid, uid) < 0) {
396 perror_msg_and_die("setreuid");
402 # define fopen_for_output fopen64
404 # define fopen_for_output fopen
408 strace_fopen(const char *path)
413 fp = fopen_for_output(path, "w");
415 perror_msg_and_die("Can't fopen '%s'", path);
417 set_cloexec_flag(fileno(fp));
421 static int popen_pid = 0;
424 # define _PATH_BSHELL "/bin/sh"
428 * We cannot use standard popen(3) here because we have to distinguish
429 * popen child process from other processes we trace, and standard popen(3)
430 * does not export its child's pid.
433 strace_popen(const char *command)
440 perror_msg_and_die("pipe");
442 set_cloexec_flag(fds[1]); /* never fails */
446 perror_msg_and_die("vfork");
448 if (popen_pid == 0) {
453 perror_msg_and_die("dup2");
456 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
457 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
463 fp = fdopen(fds[1], "w");
470 newoutf(struct tcb *tcp)
472 if (outfname && followfork > 1) {
473 char name[520 + sizeof(int) * 3];
474 sprintf(name, "%.512s.%u", outfname, tcp->pid);
475 tcp->outf = strace_fopen(name);
486 * Block user interruptions as we would leave the traced
487 * process stopped (process state T) if we would terminate in
488 * between PTRACE_ATTACH and wait4() on SIGSTOP.
489 * We rely on cleanup() from this point on.
492 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
494 if (daemonized_tracer) {
497 perror_msg_and_die("fork");
499 if (pid) { /* parent */
501 * Wait for grandchild to attach to straced process
502 * (grandparent). Grandchild SIGKILLs us after it attached.
503 * Grandparent's wait() is unblocked by our death,
504 * it proceeds to exec the straced program.
507 _exit(0); /* paranoia */
510 /* We will be the tracer process. Remember our new pid: */
511 strace_tracer_pid = getpid();
514 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
517 /* Is this a process we should attach to, but not yet attached? */
518 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
521 /* Reinitialize the output since it may have changed */
526 if (proc_open(tcp, 1) < 0) {
527 fprintf(stderr, "trouble opening proc file\n");
531 #else /* !USE_PROCFS */
533 if (followfork && !daemonized_tracer) {
534 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
537 sprintf(procdir, "/proc/%d/task", tcp->pid);
538 dir = opendir(procdir);
540 unsigned int ntid = 0, nerr = 0;
543 while ((de = readdir(dir)) != NULL) {
547 if (de->d_fileno == 0)
549 tid = atoi(de->d_name);
553 if (ptrace_attach_or_seize(tid) < 0) {
556 fprintf(stderr, "attach to pid %d failed\n", tid);
560 fprintf(stderr, "attach to pid %d succeeded\n", tid);
563 cur_tcp = alloctcb(tid);
564 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
568 sigprocmask(SIG_SETMASK, &empty_set, NULL);
571 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
575 perror("attach: ptrace(PTRACE_ATTACH, ...)");
580 fprintf(stderr, ntid > 1
581 ? "Process %u attached with %u threads - interrupt to quit\n"
582 : "Process %u attached - interrupt to quit\n",
585 if (!(tcp->flags & TCB_STARTUP)) {
586 /* -p PID, we failed to attach to PID itself
587 * but did attach to some of its sibling threads.
593 } /* if (opendir worked) */
596 if (ptrace_attach_or_seize(tcp->pid) < 0) {
597 perror("attach: ptrace(PTRACE_ATTACH, ...)");
601 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
603 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
605 if (daemonized_tracer) {
607 * It is our grandparent we trace, not a -p PID.
608 * Don't want to just detach on exit, so...
610 tcp->flags &= ~TCB_ATTACHED;
612 * Make parent go away.
613 * Also makes grandparent's wait() unblock.
615 kill(getppid(), SIGKILL);
618 #endif /* !USE_PROCFS */
621 "Process %u attached - interrupt to quit\n",
623 } /* for each tcbtab[] */
627 sigprocmask(SIG_SETMASK, &empty_set, NULL);
631 startup_child(char **argv)
634 const char *filename;
635 char pathname[MAXPATHLEN];
640 if (strchr(filename, '/')) {
641 if (strlen(filename) > sizeof pathname - 1) {
642 errno = ENAMETOOLONG;
643 perror_msg_and_die("exec");
645 strcpy(pathname, filename);
647 #ifdef USE_DEBUGGING_EXEC
649 * Debuggers customarily check the current directory
650 * first regardless of the path but doing that gives
651 * security geeks a panic attack.
653 else if (stat(filename, &statbuf) == 0)
654 strcpy(pathname, filename);
655 #endif /* USE_DEBUGGING_EXEC */
660 for (path = getenv("PATH"); path && *path; path += m) {
661 const char *colon = strchr(path, ':');
667 m = n = strlen(path);
669 if (!getcwd(pathname, MAXPATHLEN))
671 len = strlen(pathname);
673 else if (n > sizeof pathname - 1)
676 strncpy(pathname, path, n);
679 if (len && pathname[len - 1] != '/')
680 pathname[len++] = '/';
681 strcpy(pathname + len, filename);
682 if (stat(pathname, &statbuf) == 0 &&
683 /* Accept only regular files
684 with some execute bits set.
685 XXX not perfect, might still fail */
686 S_ISREG(statbuf.st_mode) &&
687 (statbuf.st_mode & 0111))
691 if (stat(pathname, &statbuf) < 0) {
692 perror_msg_and_die("Can't stat '%s'", filename);
694 strace_child = pid = fork();
696 perror_msg_and_die("fork");
698 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
699 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
706 /* Kludge for SGI, see proc_open for details. */
707 sa.sa_handler = foobar;
709 sigemptyset(&sa.sa_mask);
710 sigaction(SIGINT, &sa, NULL);
717 #else /* !USE_PROCFS */
718 if (!daemonized_tracer && !use_seize) {
719 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
720 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
724 if (username != NULL) {
725 uid_t run_euid = run_uid;
726 gid_t run_egid = run_gid;
728 if (statbuf.st_mode & S_ISUID)
729 run_euid = statbuf.st_uid;
730 if (statbuf.st_mode & S_ISGID)
731 run_egid = statbuf.st_gid;
733 * It is important to set groups before we
734 * lose privileges on setuid.
736 if (initgroups(username, run_gid) < 0) {
737 perror_msg_and_die("initgroups");
739 if (setregid(run_gid, run_egid) < 0) {
740 perror_msg_and_die("setregid");
742 if (setreuid(run_uid, run_euid) < 0) {
743 perror_msg_and_die("setreuid");
746 else if (geteuid() != 0)
747 setreuid(run_uid, run_uid);
749 if (!daemonized_tracer) {
751 * Induce a ptrace stop. Tracer (our parent)
752 * will resume us with PTRACE_SYSCALL and display
753 * the immediately following execve syscall.
754 * Can't do this on NOMMU systems, we are after
755 * vfork: parent is blocked, stopping would deadlock.
760 struct sigaction sv_sigchld;
761 sigaction(SIGCHLD, NULL, &sv_sigchld);
763 * Make sure it is not SIG_IGN, otherwise wait
766 signal(SIGCHLD, SIG_DFL);
768 * Wait for grandchild to attach to us.
769 * It kills child after that, and wait() unblocks.
774 sigaction(SIGCHLD, &sv_sigchld, NULL);
776 #endif /* !USE_PROCFS */
778 execv(pathname, argv);
779 perror_msg_and_die("exec");
782 /* We are the tracer */
784 if (!daemonized_tracer) {
786 /* child did PTRACE_TRACEME, nothing to do in parent */
788 if (!strace_vforked) {
789 /* Wait until child stopped itself */
791 while (waitpid(pid, &status, WSTOPPED) < 0) {
794 perror_msg_and_die("waitpid");
796 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
798 perror_msg_and_die("Unexpected wait status %x", status);
801 /* Else: vforked case, we have no way to sync.
802 * Just attach to it as soon as possible.
803 * This means that we may miss a few first syscalls...
806 if (ptrace_attach_or_seize(pid)) {
808 perror_msg_and_die("Can't attach to %d", pid);
815 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
817 tcp->flags |= TCB_STARTUP;
820 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
821 strace_tracer_pid = getpid();
822 /* The tracee is our parent: */
825 /* We want subsequent startup_attach() to attach to it: */
826 tcp->flags |= TCB_ATTACHED;
829 if (proc_open(tcp, 0) < 0) {
830 perror_msg_and_die("trouble opening proc file");
836 static void kill_save_errno(pid_t pid, int sig)
838 int saved_errno = errno;
840 (void) kill(pid, sig);
845 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
846 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
847 * and then see which options are supported by the kernel.
850 test_ptrace_setoptions_followfork(void)
852 int pid, expected_grandchild = 0, found_grandchild = 0;
853 const unsigned int test_options = PTRACE_O_TRACECLONE |
859 perror_msg_and_die("fork");
862 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
863 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
867 perror_msg_and_die("fork");
872 int status, tracee_pid;
875 tracee_pid = wait(&status);
876 if (tracee_pid <= 0) {
879 else if (errno == ECHILD)
881 kill_save_errno(pid, SIGKILL);
882 perror_msg_and_die("%s: unexpected wait result %d",
883 __func__, tracee_pid);
885 if (WIFEXITED(status)) {
886 if (WEXITSTATUS(status)) {
887 if (tracee_pid != pid)
888 kill_save_errno(pid, SIGKILL);
889 error_msg_and_die("%s: unexpected exit status %u",
890 __func__, WEXITSTATUS(status));
894 if (WIFSIGNALED(status)) {
895 if (tracee_pid != pid)
896 kill_save_errno(pid, SIGKILL);
897 error_msg_and_die("%s: unexpected signal %u",
898 __func__, WTERMSIG(status));
900 if (!WIFSTOPPED(status)) {
901 if (tracee_pid != pid)
902 kill_save_errno(tracee_pid, SIGKILL);
904 error_msg_and_die("%s: unexpected wait status %x",
907 if (tracee_pid != pid) {
908 found_grandchild = tracee_pid;
909 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
910 kill_save_errno(tracee_pid, SIGKILL);
911 kill_save_errno(pid, SIGKILL);
912 perror_msg_and_die("PTRACE_CONT doesn't work");
916 switch (WSTOPSIG(status)) {
918 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
919 && errno != EINVAL && errno != EIO)
920 perror_msg("PTRACE_SETOPTIONS");
923 if (status >> 16 == PTRACE_EVENT_FORK) {
926 if (ptrace(PTRACE_GETEVENTMSG, pid,
927 NULL, (long) &msg) == 0)
928 expected_grandchild = msg;
932 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
933 kill_save_errno(pid, SIGKILL);
934 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
937 if (expected_grandchild && expected_grandchild == found_grandchild) {
938 ptrace_setoptions |= test_options;
940 fprintf(stderr, "ptrace_setoptions = %#x\n",
944 error_msg("Test for PTRACE_O_TRACECLONE failed, "
945 "giving up using this feature.");
949 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
950 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
951 * and then see whether it will stop with (SIGTRAP | 0x80).
953 * Use of this option enables correct handling of user-generated SIGTRAPs,
954 * and SIGTRAPs generated by special instructions such as int3 on x86:
955 * _start: .globl _start
960 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
963 test_ptrace_setoptions_for_all(void)
965 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
972 perror_msg_and_die("fork");
976 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
977 /* Note: exits with exitcode 1 */
978 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
981 _exit(0); /* parent should see entry into this syscall */
985 int status, tracee_pid;
988 tracee_pid = wait(&status);
989 if (tracee_pid <= 0) {
992 kill_save_errno(pid, SIGKILL);
993 perror_msg_and_die("%s: unexpected wait result %d",
994 __func__, tracee_pid);
996 if (WIFEXITED(status)) {
997 if (WEXITSTATUS(status) == 0)
999 error_msg_and_die("%s: unexpected exit status %u",
1000 __func__, WEXITSTATUS(status));
1002 if (WIFSIGNALED(status)) {
1003 error_msg_and_die("%s: unexpected signal %u",
1004 __func__, WTERMSIG(status));
1006 if (!WIFSTOPPED(status)) {
1008 error_msg_and_die("%s: unexpected wait status %x",
1011 if (WSTOPSIG(status) == SIGSTOP) {
1013 * We don't check "options aren't accepted" error.
1014 * If it happens, we'll never get (SIGTRAP | 0x80),
1015 * and thus will decide to not use the option.
1016 * IOW: the outcome of the test will be correct.
1018 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1019 && errno != EINVAL && errno != EIO)
1020 perror_msg("PTRACE_SETOPTIONS");
1022 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1025 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
1026 kill_save_errno(pid, SIGKILL);
1027 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
1032 syscall_trap_sig = (SIGTRAP | 0x80);
1033 ptrace_setoptions |= test_options;
1035 fprintf(stderr, "ptrace_setoptions = %#x\n",
1040 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1041 "giving up using this feature.");
1046 test_ptrace_seize(void)
1052 perror_msg_and_die("fork");
1059 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1060 * attaching tracee continues to run unless a trap condition occurs.
1061 * PTRACE_SEIZE doesn't affect signal or group stop state.
1063 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1064 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1066 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1072 int status, tracee_pid;
1075 tracee_pid = waitpid(pid, &status, 0);
1076 if (tracee_pid <= 0) {
1079 perror_msg_and_die("%s: unexpected wait result %d",
1080 __func__, tracee_pid);
1082 if (WIFSIGNALED(status)) {
1085 error_msg_and_die("%s: unexpected wait status %x",
1089 # else /* !USE_SEIZE */
1090 # define test_ptrace_seize() ((void)0)
1095 /* Noinline: don't want main to have struct utsname permanently on stack */
1096 static void __attribute__ ((noinline))
1097 get_os_release(void)
1101 perror_msg_and_die("uname");
1102 os_release = strdup(u.release);
1104 die_out_of_memory();
1108 main(int argc, char *argv[])
1113 struct sigaction sa;
1115 progname = argv[0] ? argv[0] : "strace";
1117 strace_tracer_pid = getpid();
1121 /* Allocate the initial tcbtab. */
1122 tcbtabsize = argc; /* Surely enough for all -p args. */
1123 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
1125 die_out_of_memory();
1126 tcp = calloc(tcbtabsize, sizeof(*tcp));
1128 die_out_of_memory();
1129 for (c = 0; c < tcbtabsize; c++)
1133 set_sortby(DEFAULT_SORTBY);
1134 set_personality(DEFAULT_PERSONALITY);
1135 qualify("trace=all");
1136 qualify("abbrev=all");
1137 qualify("verbose=all");
1138 qualify("signal=all");
1139 while ((c = getopt(argc, argv,
1144 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
1147 if (cflag == CFLAG_BOTH) {
1148 error_msg_and_die("-c and -C are mutually exclusive options");
1150 cflag = CFLAG_ONLY_STATS;
1153 if (cflag == CFLAG_ONLY_STATS) {
1154 error_msg_and_die("-c and -C are mutually exclusive options");
1163 daemonized_tracer = 1;
1198 qualify("abbrev=none");
1201 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
1205 not_failing_only = 1;
1208 acolumn = atoi(optarg);
1210 error_msg_and_die("Bad column width '%s'", optarg);
1216 outfname = strdup(optarg);
1219 set_overhead(atoi(optarg));
1224 error_msg("Invalid process id: '%s'", optarg);
1227 if (pid == strace_tracer_pid) {
1228 error_msg("I'm sorry, I can't let you do that, Dave.");
1231 tcp = alloc_tcb(pid, 0);
1232 tcp->flags |= TCB_ATTACHED;
1237 if (pathtrace_select(optarg)) {
1238 error_msg_and_die("Failed to select path '%s'", optarg);
1242 max_strlen = atoi(optarg);
1243 if (max_strlen < 0) {
1244 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1251 username = strdup(optarg);
1254 if (putenv(optarg) < 0)
1255 die_out_of_memory();
1258 opt_intr = atoi(optarg);
1259 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1260 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1269 /* argc -= optind; - no need, argc is not used below */
1271 acolumn_spaces = malloc(acolumn + 1);
1272 if (!acolumn_spaces)
1273 die_out_of_memory();
1274 memset(acolumn_spaces, ' ', acolumn);
1275 acolumn_spaces[acolumn] = '\0';
1277 /* Must have PROG [ARGS], or -p PID. Not both. */
1278 if (!argv[0] == !pflag_seen)
1281 if (pflag_seen && daemonized_tracer) {
1282 error_msg_and_die("-D and -p are mutually exclusive options");
1288 if (followfork > 1 && cflag) {
1289 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1292 /* See if they want to run as another user. */
1293 if (username != NULL) {
1294 struct passwd *pent;
1296 if (getuid() != 0 || geteuid() != 0) {
1297 error_msg_and_die("You must be root to use the -u option");
1299 pent = getpwnam(username);
1301 error_msg_and_die("Cannot find user '%s'", username);
1303 run_uid = pent->pw_uid;
1304 run_gid = pent->pw_gid;
1313 test_ptrace_setoptions_followfork();
1314 test_ptrace_setoptions_for_all();
1315 test_ptrace_seize();
1318 /* Check if they want to redirect the output. */
1320 /* See if they want to pipe the output. */
1321 if (outfname[0] == '|' || outfname[0] == '!') {
1323 * We can't do the <outfname>.PID funny business
1324 * when using popen, so prohibit it.
1327 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1328 outf = strace_popen(outfname + 1);
1330 else if (followfork <= 1)
1331 outf = strace_fopen(outfname);
1334 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1335 char *buf = malloc(BUFSIZ);
1337 die_out_of_memory();
1338 setvbuf(outf, buf, _IOLBF, BUFSIZ);
1340 if (outfname && argv[0]) {
1342 opt_intr = INTR_NEVER;
1346 opt_intr = INTR_WHILE_WAIT;
1348 /* argv[0] -pPID -oFILE Default interactive setting
1349 * yes 0 0 INTR_WHILE_WAIT
1350 * no 1 0 INTR_WHILE_WAIT
1351 * yes 0 1 INTR_NEVER
1352 * no 1 1 INTR_WHILE_WAIT
1355 /* STARTUP_CHILD must be called before the signal handlers get
1356 installed below as they are inherited into the spawned process.
1357 Also we do not need to be protected by them as during interruption
1358 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1360 startup_child(argv);
1362 sigemptyset(&empty_set);
1363 sigemptyset(&blocked_set);
1364 sa.sa_handler = SIG_IGN;
1365 sigemptyset(&sa.sa_mask);
1367 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1368 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1369 if (opt_intr != INTR_ANYWHERE) {
1370 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1371 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1373 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1374 * fatal signals are blocked while syscall stop is processed,
1375 * and acted on in between, when waiting for new syscall stops.
1376 * In non-interactive mode, signals are ignored.
1378 if (opt_intr == INTR_WHILE_WAIT) {
1379 sigaddset(&blocked_set, SIGHUP);
1380 sigaddset(&blocked_set, SIGINT);
1381 sigaddset(&blocked_set, SIGQUIT);
1382 sigaddset(&blocked_set, SIGPIPE);
1383 sigaddset(&blocked_set, SIGTERM);
1384 sa.sa_handler = interrupt;
1386 /* POSIX signals on sunos4.1 are a little broken. */
1387 sa.sa_flags = SA_INTERRUPT;
1390 /* SIG_IGN, or set handler for these */
1391 sigaction(SIGHUP, &sa, NULL);
1392 sigaction(SIGINT, &sa, NULL);
1393 sigaction(SIGQUIT, &sa, NULL);
1394 sigaction(SIGPIPE, &sa, NULL);
1395 sigaction(SIGTERM, &sa, NULL);
1398 sa.sa_handler = reaper;
1399 sigaction(SIGCHLD, &sa, NULL);
1401 /* Make sure SIGCHLD has the default action so that waitpid
1402 definitely works without losing track of children. The user
1403 should not have given us a bogus state to inherit, but he might
1404 have. Arguably we should detect SIG_IGN here and pass it on
1405 to children, but probably noone really needs that. */
1406 sa.sa_handler = SIG_DFL;
1407 sigaction(SIGCHLD, &sa, NULL);
1408 #endif /* USE_PROCFS */
1410 if (pflag_seen || daemonized_tracer)
1418 if (exit_code > 0xff) {
1419 /* Avoid potential core file clobbering. */
1420 struct rlimit rlim = {0, 0};
1421 setrlimit(RLIMIT_CORE, &rlim);
1423 /* Child was killed by a signal, mimic that. */
1425 signal(exit_code, SIG_DFL);
1427 /* Paranoia - what if this signal is not fatal?
1428 Exit with 128 + signo then. */
1437 /* Allocate some more TCBs and expand the table.
1438 We don't want to relocate the TCBs because our
1439 callers have pointers and it would be a pain.
1440 So tcbtab is a table of pointers. Since we never
1441 free the TCBs, we allocate a single chunk of many. */
1443 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1444 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1445 if (!newtab || !newtcbs)
1446 die_out_of_memory();
1449 while (i < tcbtabsize)
1450 tcbtab[i++] = newtcbs++;
1454 alloc_tcb(int pid, int command_options_parsed)
1459 if (nprocs == tcbtabsize)
1462 for (i = 0; i < tcbtabsize; i++) {
1464 if ((tcp->flags & TCB_INUSE) == 0) {
1465 memset(tcp, 0, sizeof(*tcp));
1467 tcp->flags = TCB_INUSE;
1468 tcp->outf = outf; /* Initialise to current out file */
1469 #if SUPPORTED_PERSONALITIES > 1
1470 tcp->currpers = current_personality;
1477 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
1478 if (command_options_parsed)
1483 error_msg_and_die("bug in alloc_tcb");
1488 proc_open(struct tcb *tcp, int attaching)
1498 #ifndef HAVE_POLLABLE_PROCFS
1499 static int last_pfd;
1502 #ifdef HAVE_MP_PROCFS
1503 /* Open the process pseudo-files in /proc. */
1504 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1505 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1507 perror("strace: open(\"/proc/...\", ...)");
1510 set_cloexec_flag(tcp->pfd);
1511 sprintf(proc, "/proc/%d/status", tcp->pid);
1512 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1513 if (tcp->pfd_stat < 0) {
1514 perror("strace: open(\"/proc/...\", ...)");
1517 set_cloexec_flag(tcp->pfd_stat);
1518 sprintf(proc, "/proc/%d/as", tcp->pid);
1519 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1520 if (tcp->pfd_as < 0) {
1521 perror("strace: open(\"/proc/...\", ...)");
1524 set_cloexec_flag(tcp->pfd_as);
1526 /* Open the process pseudo-file in /proc. */
1528 sprintf(proc, "/proc/%d", tcp->pid);
1529 tcp->pfd = open(proc, O_RDWR|O_EXCL);
1531 sprintf(proc, "/proc/%d/mem", tcp->pid);
1532 tcp->pfd = open(proc, O_RDWR);
1535 perror("strace: open(\"/proc/...\", ...)");
1538 set_cloexec_flag(tcp->pfd);
1541 sprintf(proc, "/proc/%d/regs", tcp->pid);
1542 tcp->pfd_reg = open(proc, O_RDONLY);
1543 if (tcp->pfd_reg < 0) {
1544 perror("strace: open(\"/proc/.../regs\", ...)");
1548 sprintf(proc, "/proc/%d/status", tcp->pid);
1549 tcp->pfd_status = open(proc, O_RDONLY);
1550 if (tcp->pfd_status < 0) {
1551 perror("strace: open(\"/proc/.../status\", ...)");
1555 tcp->pfd_status = -1;
1556 #endif /* FREEBSD */
1560 * Wait for the child to pause. Because of a race
1561 * condition we have to poll for the event.
1564 if (IOCTL_STATUS(tcp) < 0) {
1565 perror("strace: PIOCSTATUS");
1568 if (tcp->status.PR_FLAGS & PR_ASLEEP)
1573 /* Stop the process so that we own the stop. */
1574 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
1575 perror("strace: PIOCSTOP");
1580 /* Set Run-on-Last-Close. */
1582 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
1583 perror("PIOCSET PR_RLC");
1586 /* Set or Reset Inherit-on-Fork. */
1588 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
1589 perror("PIOC{SET,RESET} PR_FORK");
1592 #else /* !PIOCSET */
1594 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1598 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1599 perror("PIOC{S,R}FORK");
1603 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1604 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1609 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1613 #endif /* FREEBSD */
1614 #endif /* !PIOCSET */
1616 /* Enable all syscall entries we care about. */
1617 premptyset(&syscalls);
1618 for (i = 1; i < MAX_QUALS; ++i) {
1619 if (i > (sizeof syscalls) * CHAR_BIT) break;
1620 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
1622 praddset(&syscalls, SYS_execve);
1624 praddset(&syscalls, SYS_fork);
1626 praddset(&syscalls, SYS_forkall);
1629 praddset(&syscalls, SYS_fork1);
1632 praddset(&syscalls, SYS_rfork1);
1635 praddset(&syscalls, SYS_rforkall);
1638 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
1639 perror("PIOCSENTRY");
1642 /* Enable the syscall exits. */
1643 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
1647 /* Enable signals we care about. */
1648 premptyset(&signals);
1649 for (i = 1; i < MAX_QUALS; ++i) {
1650 if (i > (sizeof signals) * CHAR_BIT) break;
1651 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
1653 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
1654 perror("PIOCSTRACE");
1657 /* Enable faults we care about */
1658 premptyset(&faults);
1659 for (i = 1; i < MAX_QUALS; ++i) {
1660 if (i > (sizeof faults) * CHAR_BIT) break;
1661 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
1663 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
1664 perror("PIOCSFAULT");
1668 /* set events flags. */
1669 arg = S_SIG | S_SCE | S_SCX;
1670 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1674 #endif /* FREEBSD */
1678 * The SGI PRSABORT doesn't work for pause() so
1679 * we send it a caught signal to wake it up.
1681 kill(tcp->pid, SIGINT);
1684 /* The child is in a pause(), abort it. */
1686 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1693 /* wake up the child if it received the SIGSTOP */
1694 kill(tcp->pid, SIGCONT);
1697 /* Wait for the child to do something. */
1698 if (IOCTL_WSTOP(tcp) < 0) {
1699 perror("PIOCWSTOP");
1702 if (tcp->status.PR_WHY == PR_SYSENTRY) {
1703 tcp->flags &= ~TCB_INSYSCALL;
1705 if (SCNO_IN_RANGE(tcp->scno) &&
1706 sysent[tcp->scno].sys_func == sys_execve)
1709 /* Set it running: maybe execve will be next. */
1712 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1714 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1721 /* handle the case where we "opened" the child before
1722 it did the kill -STOP */
1723 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1724 tcp->status.PR_WHAT == SIGSTOP)
1725 kill(tcp->pid, SIGCONT);
1731 if (attaching < 2) {
1732 /* We are attaching to an already running process.
1733 * Try to figure out the state of the process in syscalls,
1734 * to handle the first event well.
1735 * This is done by having a look at the "wchan" property of the
1736 * process, which tells where it is stopped (if it is). */
1738 char wchan[20]; /* should be enough */
1740 sprintf(proc, "/proc/%d/status", tcp->pid);
1741 status = fopen(proc, "r");
1743 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1744 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1745 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1746 strcmp(wchan, "stopevent")) {
1747 /* The process is asleep in the middle of a syscall.
1748 Fake the syscall entry event */
1749 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1750 tcp->status.PR_WHY = PR_SYSENTRY;
1755 } /* otherwise it's a fork being followed */
1757 #endif /* FREEBSD */
1758 #ifndef HAVE_POLLABLE_PROCFS
1759 if (proc_poll_pipe[0] != -1)
1760 proc_poller(tcp->pfd);
1761 else if (nprocs > 1) {
1763 proc_poller(last_pfd);
1764 proc_poller(tcp->pfd);
1766 last_pfd = tcp->pfd;
1767 #endif /* !HAVE_POLLABLE_PROCFS */
1771 #endif /* USE_PROCFS */
1781 for (i = 0; i < tcbtabsize; i++) {
1782 struct tcb *tcp = tcbtab[i];
1783 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1793 first_used_tcb(void)
1797 for (i = 0; i < tcbtabsize; i++) {
1799 if (tcp->flags & TCB_INUSE)
1810 for (i = 0; i < tcbtabsize; i++) {
1811 struct tcb *tcp = tcbtab[i];
1812 if (tcp->pfd != pfd)
1814 if (tcp->flags & TCB_INUSE)
1820 #endif /* USE_PROCFS */
1823 droptcb(struct tcb *tcp)
1830 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1833 if (tcp->pfd != -1) {
1837 if (tcp->pfd_reg != -1) {
1838 close(tcp->pfd_reg);
1841 if (tcp->pfd_status != -1) {
1842 close(tcp->pfd_status);
1843 tcp->pfd_status = -1;
1846 tcp->flags = 0; /* rebuild_pollv needs it */
1851 if (outfname && followfork > 1 && tcp->outf)
1854 memset(tcp, 0, sizeof(*tcp));
1857 /* detach traced process; continue with sig
1858 Never call DETACH twice on the same process as both unattached and
1859 attached-unstopped processes give the same ESRCH. For unattached process we
1860 would SIGSTOP it and wait for its SIGSTOP notification forever. */
1863 detach(struct tcb *tcp)
1867 int status, catch_sigstop;
1870 if (tcp->flags & TCB_BPTSET)
1875 * Linux wrongly insists the child be stopped
1876 * before detaching. Arghh. We go through hoops
1877 * to make a clean break of things.
1880 #undef PTRACE_DETACH
1881 #define PTRACE_DETACH PTRACE_SUNDETACH
1884 * We attached but possibly didn't see the expected SIGSTOP.
1885 * We must catch exactly one as otherwise the detached process
1886 * would be left stopped (process state T).
1888 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1889 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1891 /* On a clear day, you can see forever. */
1893 else if (errno != ESRCH) {
1894 /* Shouldn't happen. */
1895 perror("detach: ptrace(PTRACE_DETACH, ...)");
1897 else if (my_tkill(tcp->pid, 0) < 0) {
1899 perror("detach: checking sanity");
1901 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
1903 perror("detach: stopping child");
1907 if (catch_sigstop) {
1910 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1911 if (errno == ECHILD) /* Already gone. */
1913 if (errno != EINVAL) {
1914 perror("detach: waiting");
1918 /* No __WALL here. */
1919 if (waitpid(tcp->pid, &status, 0) < 0) {
1920 if (errno != ECHILD) {
1921 perror("detach: waiting");
1925 /* If no processes, try clones. */
1926 if (wait4(tcp->pid, &status, __WCLONE,
1928 if (errno != ECHILD)
1929 perror("detach: waiting");
1932 #endif /* __WCLONE */
1937 if (!WIFSTOPPED(status)) {
1938 /* Au revoir, mon ami. */
1941 if (WSTOPSIG(status) == SIGSTOP) {
1942 ptrace_restart(PTRACE_DETACH, tcp, 0);
1945 error = ptrace_restart(PTRACE_CONT, tcp,
1946 WSTOPSIG(status) == syscall_trap_sig ? 0
1947 : WSTOPSIG(status));
1955 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1956 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
1960 fprintf(stderr, "Process %u detached\n", tcp->pid);
1969 static void reaper(int sig)
1974 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1978 #endif /* USE_PROCFS */
1987 /* 'interrupted' is a volatile object, fetch it only once */
1988 fatal_sig = interrupted;
1990 fatal_sig = SIGTERM;
1992 for (i = 0; i < tcbtabsize; i++) {
1994 if (!(tcp->flags & TCB_INUSE))
1998 "cleanup: looking at pid %u\n", tcp->pid);
2000 (!outfname || followfork < 2 || printing_tcp == tcp)) {
2001 tprints(" <unfinished ...>\n");
2002 printing_tcp = NULL;
2004 if (tcp->flags & TCB_ATTACHED)
2007 kill(tcp->pid, SIGCONT);
2008 kill(tcp->pid, fatal_sig);
2021 #ifndef HAVE_STRERROR
2023 #if !HAVE_DECL_SYS_ERRLIST
2024 extern int sys_nerr;
2025 extern char *sys_errlist[];
2026 #endif /* HAVE_DECL_SYS_ERRLIST */
2029 strerror(int err_no)
2031 static char buf[64];
2033 if (err_no < 1 || err_no >= sys_nerr) {
2034 sprintf(buf, "Unknown error %d", err_no);
2037 return sys_errlist[err_no];
2040 #endif /* HAVE_STERRROR */
2042 #ifndef HAVE_STRSIGNAL
2044 #if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
2045 extern char *sys_siglist[];
2047 #if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
2048 extern char *_sys_siglist[];
2054 static char buf[64];
2056 if (sig < 1 || sig >= NSIG) {
2057 sprintf(buf, "Unknown signal %d", sig);
2060 #ifdef HAVE__SYS_SIGLIST
2061 return _sys_siglist[sig];
2063 return sys_siglist[sig];
2067 #endif /* HAVE_STRSIGNAL */
2077 pollv = malloc(nprocs * sizeof(pollv[0]));
2079 die_out_of_memory();
2081 for (i = j = 0; i < tcbtabsize; i++) {
2082 struct tcb *tcp = tcbtab[i];
2083 if (!(tcp->flags & TCB_INUSE))
2085 pollv[j].fd = tcp->pfd;
2086 pollv[j].events = POLLWANT;
2090 error_msg_and_die("proc miscount");
2094 #ifndef HAVE_POLLABLE_PROCFS
2097 proc_poll_open(void)
2101 if (pipe(proc_poll_pipe) < 0) {
2102 perror_msg_and_die("pipe");
2104 for (i = 0; i < 2; i++) {
2105 set_cloexec_flag(proc_poll_pipe[i]);
2110 proc_poll(struct pollfd *pollv, int nfds, int timeout)
2114 struct proc_pollfd pollinfo;
2116 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
2119 if (n != sizeof(struct proc_pollfd)) {
2120 error_msg_and_die("panic: short read: %d", n);
2122 for (i = 0; i < nprocs; i++) {
2123 if (pollv[i].fd == pollinfo.fd)
2124 pollv[i].revents = pollinfo.revents;
2126 pollv[i].revents = 0;
2128 poller_pid = pollinfo.pid;
2133 wakeup_handler(int sig)
2138 proc_poller(int pfd)
2140 struct proc_pollfd pollinfo;
2141 struct sigaction sa;
2142 sigset_t blocked_set, empty_set;
2147 struct procfs_status pfs;
2148 #endif /* FREEBSD */
2152 perror_msg_and_die("fork");
2159 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2161 sigemptyset(&sa.sa_mask);
2162 sigaction(SIGHUP, &sa, NULL);
2163 sigaction(SIGINT, &sa, NULL);
2164 sigaction(SIGQUIT, &sa, NULL);
2165 sigaction(SIGPIPE, &sa, NULL);
2166 sigaction(SIGTERM, &sa, NULL);
2167 sa.sa_handler = wakeup_handler;
2168 sigaction(SIGUSR1, &sa, NULL);
2169 sigemptyset(&blocked_set);
2170 sigaddset(&blocked_set, SIGUSR1);
2171 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2172 sigemptyset(&empty_set);
2174 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
2175 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
2178 for (i = 0; i < n; i++) {
2179 if (i != pfd && i != proc_poll_pipe[1])
2184 pollinfo.pid = getpid();
2187 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2189 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2196 pollinfo.revents = POLLERR;
2199 pollinfo.revents = POLLHUP;
2202 perror("proc_poller: PIOCWSTOP");
2204 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2207 pollinfo.revents = POLLWANT;
2208 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2209 sigsuspend(&empty_set);
2213 #endif /* !HAVE_POLLABLE_PROCFS */
2223 if (followfork < 2 &&
2224 last < nprocs && (pollv[last].revents & POLLWANT)) {
2226 * The previous process is ready to run again. We'll
2227 * let it do so if it is currently in a syscall. This
2228 * heuristic improves the readability of the trace.
2230 tcp = pfd2tcb(pollv[last].fd);
2231 if (tcp && exiting(tcp))
2232 return pollv[last].fd;
2235 for (i = 0; i < nprocs; i++) {
2236 /* Let competing children run round robin. */
2237 j = (i + last + 1) % nprocs;
2238 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2239 tcp = pfd2tcb(pollv[j].fd);
2241 error_msg_and_die("lost proc");
2246 if (pollv[j].revents & POLLWANT) {
2251 error_msg_and_die("nothing ready");
2258 struct tcb *in_syscall = NULL;
2263 int ioctl_result = 0, ioctl_errno = 0;
2268 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2275 #ifndef HAVE_POLLABLE_PROCFS
2276 if (proc_poll_pipe[0] == -1) {
2278 tcp = first_used_tcb();
2285 #ifndef HAVE_POLLABLE_PROCFS
2287 /* fall through ... */
2288 #endif /* !HAVE_POLLABLE_PROCFS */
2290 #ifdef HAVE_POLLABLE_PROCFS
2292 /* On some systems (e.g. UnixWare) we get too much ugly
2293 "unfinished..." stuff when multiple proceses are in
2294 syscalls. Here's a nasty hack */
2301 pv.events = POLLWANT;
2302 what = poll(&pv, 1, 1);
2308 else if (what == 1 && pv.revents & POLLWANT) {
2314 if (poll(pollv, nprocs, INFTIM) < 0) {
2319 #else /* !HAVE_POLLABLE_PROCFS */
2320 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2325 #endif /* !HAVE_POLLABLE_PROCFS */
2332 /* Look up `pfd' in our table. */
2335 error_msg_and_die("unknown pfd: %u", pfd);
2340 /* Get the status of the process. */
2343 ioctl_result = IOCTL_WSTOP(tcp);
2345 /* Thanks to some scheduling mystery, the first poller
2346 sometimes waits for the already processed end of fork
2347 event. Doing a non blocking poll here solves the problem. */
2348 if (proc_poll_pipe[0] != -1)
2349 ioctl_result = IOCTL_STATUS(tcp);
2351 ioctl_result = IOCTL_WSTOP(tcp);
2352 #endif /* FREEBSD */
2353 ioctl_errno = errno;
2354 #ifndef HAVE_POLLABLE_PROCFS
2355 if (proc_poll_pipe[0] != -1) {
2356 if (ioctl_result < 0)
2357 kill(poller_pid, SIGKILL);
2359 kill(poller_pid, SIGUSR1);
2361 #endif /* !HAVE_POLLABLE_PROCFS */
2367 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2369 if (ioctl_result < 0) {
2370 /* Find out what happened if it failed. */
2371 switch (ioctl_errno) {
2382 perror_msg_and_die("PIOCWSTOP");
2387 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2388 /* discard first event for a syscall we never entered */
2389 IOCTL(tcp->pfd, PIOCRUN, 0);
2394 /* clear the just started flag */
2395 tcp->flags &= ~TCB_STARTUP;
2397 /* set current output file */
2399 curcol = tcp->curcol;
2402 struct timeval stime;
2407 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2411 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2412 &stime.tv_sec, &stime.tv_usec);
2414 stime.tv_sec = stime.tv_usec = 0;
2415 #else /* !FREEBSD */
2416 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2417 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2418 #endif /* !FREEBSD */
2419 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2422 what = tcp->status.PR_WHAT;
2423 switch (tcp->status.PR_WHY) {
2426 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2427 tcp->status.PR_WHY = PR_SYSENTRY;
2428 if (trace_syscall(tcp) < 0) {
2429 error_msg_and_die("syscall trouble");
2433 #endif /* !FREEBSD */
2439 if (trace_syscall(tcp) < 0) {
2440 error_msg_and_die("syscall trouble");
2444 if (cflag != CFLAG_ONLY_STATS
2445 && (qual_flags[what] & QUAL_SIGNAL)) {
2447 tprintf("--- %s (%s) ---\n",
2448 signame(what), strsignal(what));
2449 printing_tcp = NULL;
2451 if (tcp->status.PR_INFO.si_signo == what) {
2453 tprints(" siginfo=");
2454 printsiginfo(&tcp->status.PR_INFO, 1);
2456 printing_tcp = NULL;
2462 if (cflag != CFLAGS_ONLY_STATS
2463 && (qual_flags[what] & QUAL_FAULT)) {
2465 tprintf("=== FAULT %d ===\n", what);
2466 printing_tcp = NULL;
2470 case 0: /* handle case we polled for nothing */
2474 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
2477 /* Remember current print column before continuing. */
2478 tcp->curcol = curcol;
2481 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2483 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2486 perror_msg_and_die("PIOCRUN");
2492 #else /* !USE_PROCFS */
2499 struct rusage *rup = cflag ? &ru : NULL;
2501 static int wait4_options = __WALL;
2505 while (nprocs != 0) {
2516 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2519 pid = wait4(-1, &status, wait4_options, rup);
2520 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
2521 /* this kernel does not support __WALL */
2522 wait4_options &= ~__WALL;
2523 pid = wait4(-1, &status, wait4_options, rup);
2525 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
2526 /* most likely a "cloned" process */
2527 pid = wait4(-1, &status, __WCLONE, rup);
2529 perror_msg("wait4(__WCLONE) failed");
2533 pid = wait4(-1, &status, 0, rup);
2534 # endif /* __WALL */
2537 pid = wait(&status);
2541 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2544 switch (wait_errno) {
2549 * We would like to verify this case
2550 * but sometimes a race in Solbourne's
2551 * version of SunOS sometimes reports
2552 * ECHILD before sending us SIGCHILD.
2557 perror("strace: wait");
2561 if (pid == popen_pid) {
2562 if (WIFEXITED(status) || WIFSIGNALED(status))
2567 event = ((unsigned)status >> 16);
2569 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2572 static const char *const event_names[] = {
2573 [PTRACE_EVENT_CLONE] = "CLONE",
2574 [PTRACE_EVENT_FORK] = "FORK",
2575 [PTRACE_EVENT_VFORK] = "VFORK",
2576 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2577 [PTRACE_EVENT_EXEC] = "EXEC",
2578 [PTRACE_EVENT_EXIT] = "EXIT",
2581 if (event < ARRAY_SIZE(event_names))
2582 e = event_names[event];
2584 sprintf(buf, "?? (%u)", event);
2587 fprintf(stderr, " PTRACE_EVENT_%s", e);
2591 if (WIFSIGNALED(status))
2593 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2594 WCOREDUMP(status) ? "core," : "",
2595 signame(WTERMSIG(status)));
2597 sprintf(buf, "WIFSIGNALED,sig=%s",
2598 signame(WTERMSIG(status)));
2600 if (WIFEXITED(status))
2601 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2602 if (WIFSTOPPED(status))
2603 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
2605 if (WIFCONTINUED(status))
2606 strcpy(buf, "WIFCONTINUED");
2608 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2611 /* Look up 'pid' in our table. */
2615 /* Under Linux, execve changes pid to thread leader's pid,
2616 * and we see this changed pid on EVENT_EXEC and later,
2617 * execve sysexit. Leader "disappears" without exit
2618 * notification. Let user know that, drop leader's tcb,
2619 * and fix up pid in execve thread's tcb.
2620 * Effectively, execve thread's tcb replaces leader's tcb.
2622 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2623 * on exit syscall) in multithreaded programs exactly
2624 * in order to handle this case.
2626 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2627 * On 2.6 and earlier, it can return garbage.
2629 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2631 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2635 struct tcb *execve_thread = pid2tcb(old_pid);
2638 curcol = tcp->curcol;
2641 tprints(" <unfinished ...>\n");
2643 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2644 printing_tcp = NULL;
2647 if (execve_thread) {
2648 /* swap output FILEs (needed for -ff) */
2649 tcp->outf = execve_thread->outf;
2650 execve_thread->outf = outf;
2654 tcp = execve_thread;
2657 tcp->flags |= TCB_REPRINT;
2666 /* This is needed to go with the CLONE_PTRACE
2667 changes in process.c/util.c: we might see
2668 the child's initial trap before we see the
2669 parent return from the clone syscall.
2670 Leave the child suspended until the parent
2671 returns from its system call. Only then
2672 will we have the association of parent and
2673 child so that we know how to do clearbpt
2675 tcp = alloctcb(pid);
2676 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
2678 fprintf(stderr, "Process %d attached\n",
2682 /* This can happen if a clone call used
2683 CLONE_PTRACE itself. */
2686 if (WIFSTOPPED(status))
2687 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2688 error_msg_and_die("Unknown pid: %u", pid);
2691 /* set current output file */
2693 curcol = tcp->curcol;
2696 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2697 tcp->stime = ru.ru_stime;
2701 if (WIFSIGNALED(status)) {
2702 if (pid == strace_child)
2703 exit_code = 0x100 | WTERMSIG(status);
2704 if (cflag != CFLAG_ONLY_STATS
2705 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2708 tprintf("+++ killed by %s %s+++\n",
2709 signame(WTERMSIG(status)),
2710 WCOREDUMP(status) ? "(core dumped) " : "");
2712 tprintf("+++ killed by %s +++\n",
2713 signame(WTERMSIG(status)));
2715 printing_tcp = NULL;
2721 if (WIFEXITED(status)) {
2722 if (pid == strace_child)
2723 exit_code = WEXITSTATUS(status);
2724 if (tcp == printing_tcp) {
2725 tprints(" <unfinished ...>\n");
2726 printing_tcp = NULL;
2728 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2730 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2731 printing_tcp = NULL;
2737 if (!WIFSTOPPED(status)) {
2738 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2743 /* Is this the very first time we see this tracee stopped? */
2744 if (tcp->flags & TCB_STARTUP) {
2746 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
2747 tcp->flags &= ~TCB_STARTUP;
2748 if (tcp->flags & TCB_BPTSET) {
2750 * One example is a breakpoint inherited from
2751 * parent through fork().
2753 if (clearbpt(tcp) < 0) {
2761 if (ptrace_setoptions) {
2763 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2764 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2765 if (errno != ESRCH) {
2766 /* Should never happen, really */
2767 perror_msg_and_die("PTRACE_SETOPTIONS");
2774 sig = WSTOPSIG(status);
2779 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
2781 * PTRACE_INTERRUPT-stop or group-stop.
2782 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2794 goto restart_tracee_with_sig_0;
2797 /* Is this post-attach SIGSTOP?
2798 * Interestingly, the process may stop
2799 * with STOPSIG equal to some other signal
2800 * than SIGSTOP if we happend to attach
2801 * just before the process takes a signal.
2803 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2805 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2806 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
2807 goto restart_tracee_with_sig_0;
2810 if (sig != syscall_trap_sig) {
2813 /* Nonzero (true) if tracee is stopped by signal
2814 * (as opposed to "tracee received signal").
2816 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
2820 if (cflag != CFLAG_ONLY_STATS
2821 && (qual_flags[sig] & QUAL_SIGNAL)) {
2822 #if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
2826 upeek(tcp, PT_CR_IPSR, &psr);
2827 upeek(tcp, PT_CR_IIP, &pc);
2830 pc += (psr >> PSR_RI) & 0x3;
2831 # define PC_FORMAT_STR " @ %lx"
2832 # define PC_FORMAT_ARG , pc
2834 # define PC_FORMAT_STR ""
2835 # define PC_FORMAT_ARG /* nothing */
2840 printsiginfo(&si, verbose(tcp));
2841 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
2845 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
2849 printing_tcp = NULL;
2854 /* It's signal-delivery-stop. Inject the signal */
2855 goto restart_tracee;
2857 /* It's group-stop */
2861 * This ends ptrace-stop, but does *not* end group-stop.
2862 * This makes stopping signals work properly on straced process
2863 * (that is, process really stops. It used to continue to run).
2865 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2871 /* We don't have PTRACE_LISTEN support... */
2873 goto restart_tracee;
2876 /* We handled quick cases, we are permitted to interrupt now. */
2880 /* This should be syscall entry or exit.
2881 * (Or it still can be that pesky post-execve SIGTRAP!)
2884 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2885 /* ptrace() failed in trace_syscall() with ESRCH.
2886 * Likely a result of process disappearing mid-flight.
2887 * Observed case: exit_group() terminating
2888 * all processes in thread group.
2890 if (tcp->flags & TCB_ATTACHED) {
2892 /* Do we have dangling line "syscall(param, param"?
2893 * Finish the line then.
2895 printing_tcp->flags |= TCB_REPRINT;
2896 tprints(" <unfinished ...>\n");
2897 printing_tcp = NULL;
2900 /* We assume that ptrace error was caused by process death.
2901 * We used to detach(tcp) here, but since we no longer
2902 * implement "detach before death" policy/hack,
2903 * we can let this process to report its death to us
2904 * normally, via WIFEXITED or WIFSIGNALED wait status.
2907 /* It's our real child (and we also trace it) */
2908 /* my_tkill(pid, SIGKILL); - why? */
2909 /* droptcb(tcp); - why? */
2913 restart_tracee_with_sig_0:
2916 /* Remember current print column before continuing. */
2917 tcp->curcol = curcol;
2918 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
2926 #endif /* !USE_PROCFS */
2929 tprintf(const char *fmt, ...)
2933 va_start(args, fmt);
2935 int n = vfprintf(outf, fmt, args);
2938 perror(outfname == NULL
2939 ? "<writing to pipe>" : outfname);
2947 tprints(const char *str)
2950 int n = fputs(str, outf);
2952 curcol += strlen(str);
2956 perror(outfname == NULL
2957 ? "<writing to pipe>" : outfname);
2962 printleader(struct tcb *tcp)
2965 if (printing_tcp->ptrace_errno) {
2966 if (printing_tcp->flags & TCB_INSYSCALL) {
2967 tprints(" <unavailable>) ");
2970 tprints("= ? <unavailable>\n");
2971 printing_tcp->ptrace_errno = 0;
2972 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2973 printing_tcp->flags |= TCB_REPRINT;
2974 tprints(" <unfinished ...>\n");
2980 if ((followfork == 1 || pflag_seen > 1) && outfname)
2981 tprintf("%-5d ", tcp->pid);
2982 else if (nprocs > 1 && !outfname)
2983 tprintf("[pid %5u] ", tcp->pid);
2985 char str[sizeof("HH:MM:SS")];
2986 struct timeval tv, dtv;
2987 static struct timeval otv;
2989 gettimeofday(&tv, NULL);
2991 if (otv.tv_sec == 0)
2993 tv_sub(&dtv, &tv, &otv);
2994 tprintf("%6ld.%06ld ",
2995 (long) dtv.tv_sec, (long) dtv.tv_usec);
2998 else if (tflag > 2) {
2999 tprintf("%ld.%06ld ",
3000 (long) tv.tv_sec, (long) tv.tv_usec);
3003 time_t local = tv.tv_sec;
3004 strftime(str, sizeof(str), "%T", localtime(&local));
3006 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
3008 tprintf("%s ", str);
3018 if (curcol < acolumn)
3019 tprints(acolumn_spaces + curcol);
3022 #ifdef HAVE_MP_PROCFS
3025 mp_ioctl(int fd, int cmd, void *arg, int size)
3027 struct iovec iov[2];
3030 iov[0].iov_base = &cmd;
3031 iov[0].iov_len = sizeof cmd;
3034 iov[1].iov_base = arg;
3035 iov[1].iov_len = size;
3038 return writev(fd, iov, n);