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