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