blob: 9e7f3fa3d3febdcfef345c58a3e310d90ef5d370 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
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>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * 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
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#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>
John Hughes19e49982001-10-19 08:59:12 +000046#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#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
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000064#if defined(IA64) && defined(LINUX)
65# include <asm/ptrace_offsets.h>
66#endif
67
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000068#ifdef USE_PROCFS
69#include <poll.h>
70#endif
71
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000072#ifdef SVR4
73#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000074#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000075#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000076#include <sys/uio.h>
77#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000079#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000081int debug = 0, followfork = 0, followvfork = 0;
82int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
83static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
Michal Ludvig17f8fb32002-11-06 13:17:21 +000085/* Sometimes we want to print only succeeding syscalls. */
86int not_failing_only = 0;
87
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000088static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089uid_t run_uid;
90gid_t run_gid;
91
92int acolumn = DEFAULT_ACOLUMN;
93int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000094static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +000096struct tcb **tcbtab;
97unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099extern char **environ;
100
Roland McGrath0a463882007-07-05 18:43:16 +0000101static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102static int trace P((void));
103static void cleanup P((void));
104static void interrupt P((int sig));
105static sigset_t empty_set, blocked_set;
106
107#ifdef HAVE_SIG_ATOMIC_T
108static volatile sig_atomic_t interrupted;
109#else /* !HAVE_SIG_ATOMIC_T */
110#ifdef __STDC__
111static volatile int interrupted;
112#else /* !__STDC__ */
113static int interrupted;
114#endif /* !__STDC__ */
115#endif /* !HAVE_SIG_ATOMIC_T */
116
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000117#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118
119static struct tcb *pfd2tcb P((int pfd));
120static void reaper P((int sig));
121static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000122static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123
124#ifndef HAVE_POLLABLE_PROCFS
125
126static void proc_poll_open P((void));
127static void proc_poller P((int pfd));
128
129struct proc_pollfd {
130 int fd;
131 int revents;
132 int pid;
133};
134
135static int poller_pid;
136static int proc_poll_pipe[2] = { -1, -1 };
137
138#endif /* !HAVE_POLLABLE_PROCFS */
139
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000140#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#define POLLWANT POLLWRNORM
142#else
143#define POLLWANT POLLPRI
144#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000145#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
147static void
148usage(ofp, exitval)
149FILE *ofp;
150int exitval;
151{
152 fprintf(ofp, "\
153usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000154 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
155 [command [arg ...]]\n\
156 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
157 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158-c -- count time, calls, and errors for each syscall and report summary\n\
159-f -- follow forks, -ff -- with output into separate files\n\
160-F -- attempt to follow vforks, -h -- print help message\n\
161-i -- print instruction pointer at time of syscall\n\
162-q -- suppress messages about attaching, detaching, etc.\n\
163-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
164-T -- print time spent in each syscall, -V -- print version\n\
165-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
166-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
167-a column -- alignment COLUMN for printing syscall results (default %d)\n\
168-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
169 options: trace, abbrev, verbose, raw, signal, read, or write\n\
170-o file -- send trace output to FILE instead of stderr\n\
171-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
172-p pid -- trace process with process id PID, may be repeated\n\
173-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
174-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
175-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000176-E var=val -- put var=val in the environment for command\n\
177-E var -- remove var from the environment for command\n\
178" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000179-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000180 */
181, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182 exit(exitval);
183}
184
185#ifdef SVR4
186#ifdef MIPS
187void
188foobar()
189{
190}
191#endif /* MIPS */
192#endif /* SVR4 */
193
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000194static int
195set_cloexec_flag(int fd)
196{
197 int flags, newflags;
198
199 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
200 {
201 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
202 progname, strerror(errno));
203 return -1;
204 }
205
206 newflags = flags | FD_CLOEXEC;
207 if (flags == newflags)
208 return 0;
209
210 if (fcntl(fd, F_SETFD, newflags) < 0)
211 {
212 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
213 progname, strerror(errno));
214 return -1;
215 }
216
217 return 0;
218}
219
220/*
221 * When strace is setuid executable, we have to swap uids
222 * before and after filesystem and process management operations.
223 */
224static void
225swap_uid(void)
226{
227#ifndef SVR4
228 int euid = geteuid(), uid = getuid();
229
230 if (euid != uid && setreuid(euid, uid) < 0)
231 {
232 fprintf(stderr, "%s: setreuid: %s\n",
233 progname, strerror(errno));
234 exit(1);
235 }
236#endif
237}
238
Roland McGrath4bfa6262007-07-05 20:03:16 +0000239#if _LFS64_LARGEFILE
240# define fopen_for_output fopen64
241#else
242# define fopen_for_output fopen
243#endif
244
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000245static FILE *
246strace_fopen(const char *path, const char *mode)
247{
248 FILE *fp;
249
250 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000251 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000252 fprintf(stderr, "%s: can't fopen '%s': %s\n",
253 progname, path, strerror(errno));
254 swap_uid();
255 if (fp && set_cloexec_flag(fileno(fp)) < 0)
256 {
257 fclose(fp);
258 fp = NULL;
259 }
260 return fp;
261}
262
263static int popen_pid = -1;
264
265#ifndef _PATH_BSHELL
266# define _PATH_BSHELL "/bin/sh"
267#endif
268
269/*
270 * We cannot use standard popen(3) here because we have to distinguish
271 * popen child process from other processes we trace, and standard popen(3)
272 * does not export its child's pid.
273 */
274static FILE *
275strace_popen(const char *command)
276{
277 int fds[2];
278
279 swap_uid();
280 if (pipe(fds) < 0)
281 {
282 fprintf(stderr, "%s: pipe: %s\n",
283 progname, strerror(errno));
284 swap_uid();
285 return NULL;
286 }
287
288 if (set_cloexec_flag(fds[1]) < 0)
289 {
290 close(fds[0]);
291 close(fds[1]);
292 swap_uid();
293 return NULL;
294 }
295
296 if ((popen_pid = fork()) == -1)
297 {
298 fprintf(stderr, "%s: fork: %s\n",
299 progname, strerror(errno));
300 close(fds[0]);
301 close(fds[1]);
302 swap_uid();
303 return NULL;
304 }
305
306 if (popen_pid)
307 {
308 /* parent */
309 close(fds[0]);
310 swap_uid();
311 return fdopen(fds[1], "w");
312 } else
313 {
314 /* child */
315 close(fds[1]);
316 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
317 {
318 fprintf(stderr, "%s: dup2: %s\n",
319 progname, strerror(errno));
320 _exit(1);
321 }
322 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
323 fprintf(stderr, "%s: execl: %s: %s\n",
324 progname, _PATH_BSHELL, strerror(errno));
325 _exit(1);
326 }
327}
328
329static int
330newoutf(struct tcb *tcp)
331{
332 if (outfname && followfork > 1) {
333 char name[MAXPATHLEN];
334 FILE *fp;
335
336 sprintf(name, "%s.%u", outfname, tcp->pid);
337 if ((fp = strace_fopen(name, "w")) == NULL)
338 return -1;
339 tcp->outf = fp;
340 }
341 return 0;
342}
343
Roland McGrath02203312007-06-11 22:06:31 +0000344static void
345startup_attach(void)
346{
347 int tcbi;
348 struct tcb *tcp;
349
350 /*
351 * Block user interruptions as we would leave the traced
352 * process stopped (process state T) if we would terminate in
353 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
354 * We rely on cleanup () from this point on.
355 */
356 if (interactive)
357 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
358
359 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
360 tcp = tcbtab[tcbi];
361 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
362 continue;
363#ifdef LINUX
364 if (tcp->flags & TCB_CLONE_THREAD)
365 continue;
366#endif
367 /* Reinitialize the output since it may have changed. */
368 tcp->outf = outf;
369 if (newoutf(tcp) < 0)
370 exit(1);
371
372#ifdef USE_PROCFS
373 if (proc_open(tcp, 1) < 0) {
374 fprintf(stderr, "trouble opening proc file\n");
375 droptcb(tcp);
376 continue;
377 }
378#else /* !USE_PROCFS */
379# ifdef LINUX
380 if (followfork) {
381 char procdir[MAXPATHLEN];
382 DIR *dir;
383
384 sprintf(procdir, "/proc/%d/task", tcp->pid);
385 dir = opendir(procdir);
386 if (dir != NULL) {
387 unsigned int ntid = 0, nerr = 0;
388 struct dirent *de;
389 int tid;
390 while ((de = readdir(dir)) != NULL) {
391 if (de->d_fileno == 0 ||
392 de->d_name[0] == '.')
393 continue;
394 tid = atoi(de->d_name);
395 if (tid <= 0)
396 continue;
397 ++ntid;
398 if (ptrace(PTRACE_ATTACH, tid,
399 (char *) 1, 0) < 0)
400 ++nerr;
401 else if (tid != tcbtab[tcbi]->pid) {
402 if (nprocs == tcbtabsize &&
403 expand_tcbtab())
404 tcp = NULL;
405 else
406 tcp = alloctcb(tid);
407 if (tcp == NULL)
408 exit(1);
409 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
410 tcbtab[tcbi]->nchildren++;
411 tcbtab[tcbi]->nclone_threads++;
412 tcbtab[tcbi]->nclone_detached++;
413 tcp->parent = tcbtab[tcbi];
414 }
415 if (interactive) {
416 sigprocmask(SIG_SETMASK, &empty_set, NULL);
417 if (interrupted)
418 return;
419 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
420 }
421 }
422 closedir(dir);
423 if (nerr == ntid) {
424 perror("attach: ptrace(PTRACE_ATTACH, ...)");
425 droptcb(tcp);
426 continue;
427 }
428 if (!qflag) {
429 ntid -= nerr;
430 if (ntid > 1)
431 fprintf(stderr, "\
432Process %u attached with %u threads - interrupt to quit\n",
433 tcp->pid, ntid);
434 else
435 fprintf(stderr, "\
436Process %u attached - interrupt to quit\n",
437 tcp->pid);
438 }
439 continue;
440 }
441 }
442# endif
443 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
444 perror("attach: ptrace(PTRACE_ATTACH, ...)");
445 droptcb(tcp);
446 continue;
447 }
448 /* INTERRUPTED is going to be checked at the top of TRACE. */
449#endif /* !USE_PROCFS */
450 if (!qflag)
451 fprintf(stderr,
452 "Process %u attached - interrupt to quit\n",
453 tcp->pid);
454 }
455
456 if (interactive)
457 sigprocmask(SIG_SETMASK, &empty_set, NULL);
458}
459
460static void
461startup_child (char **argv)
462{
463 struct stat statbuf;
464 const char *filename;
465 char pathname[MAXPATHLEN];
466 int pid = 0;
467 struct tcb *tcp;
468
469 filename = argv[0];
470 if (strchr(filename, '/')) {
471 if (strlen(filename) > sizeof pathname - 1) {
472 errno = ENAMETOOLONG;
473 perror("strace: exec");
474 exit(1);
475 }
476 strcpy(pathname, filename);
477 }
478#ifdef USE_DEBUGGING_EXEC
479 /*
480 * Debuggers customarily check the current directory
481 * first regardless of the path but doing that gives
482 * security geeks a panic attack.
483 */
484 else if (stat(filename, &statbuf) == 0)
485 strcpy(pathname, filename);
486#endif /* USE_DEBUGGING_EXEC */
487 else {
488 char *path;
489 int m, n, len;
490
491 for (path = getenv("PATH"); path && *path; path += m) {
492 if (strchr(path, ':')) {
493 n = strchr(path, ':') - path;
494 m = n + 1;
495 }
496 else
497 m = n = strlen(path);
498 if (n == 0) {
499 if (!getcwd(pathname, MAXPATHLEN))
500 continue;
501 len = strlen(pathname);
502 }
503 else if (n > sizeof pathname - 1)
504 continue;
505 else {
506 strncpy(pathname, path, n);
507 len = n;
508 }
509 if (len && pathname[len - 1] != '/')
510 pathname[len++] = '/';
511 strcpy(pathname + len, filename);
512 if (stat(pathname, &statbuf) == 0 &&
513 /* Accept only regular files
514 with some execute bits set.
515 XXX not perfect, might still fail */
516 S_ISREG(statbuf.st_mode) &&
517 (statbuf.st_mode & 0111))
518 break;
519 }
520 }
521 if (stat(pathname, &statbuf) < 0) {
522 fprintf(stderr, "%s: %s: command not found\n",
523 progname, filename);
524 exit(1);
525 }
526 switch (pid = fork()) {
527 case -1:
528 perror("strace: fork");
529 cleanup();
530 exit(1);
531 break;
532 case 0: {
533#ifdef USE_PROCFS
534 if (outf != stderr) close (fileno (outf));
535#ifdef MIPS
536 /* Kludge for SGI, see proc_open for details. */
537 sa.sa_handler = foobar;
538 sa.sa_flags = 0;
539 sigemptyset(&sa.sa_mask);
540 sigaction(SIGINT, &sa, NULL);
541#endif /* MIPS */
542#ifndef FREEBSD
543 pause();
544#else /* FREEBSD */
545 kill(getpid(), SIGSTOP); /* stop HERE */
546#endif /* FREEBSD */
547#else /* !USE_PROCFS */
548 if (outf!=stderr)
549 close(fileno (outf));
550
551 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
552 perror("strace: ptrace(PTRACE_TRACEME, ...)");
553 exit(1);
554 }
555 if (debug)
556 kill(getpid(), SIGSTOP);
557
558 if (username != NULL || geteuid() == 0) {
559 uid_t run_euid = run_uid;
560 gid_t run_egid = run_gid;
561
562 if (statbuf.st_mode & S_ISUID)
563 run_euid = statbuf.st_uid;
564 if (statbuf.st_mode & S_ISGID)
565 run_egid = statbuf.st_gid;
566
567 /*
568 * It is important to set groups before we
569 * lose privileges on setuid.
570 */
571 if (username != NULL) {
572 if (initgroups(username, run_gid) < 0) {
573 perror("initgroups");
574 exit(1);
575 }
576 if (setregid(run_gid, run_egid) < 0) {
577 perror("setregid");
578 exit(1);
579 }
580 if (setreuid(run_uid, run_euid) < 0) {
581 perror("setreuid");
582 exit(1);
583 }
584 }
585 }
586 else
587 setreuid(run_uid, run_uid);
588
589 /*
590 * Induce an immediate stop so that the parent
591 * will resume us with PTRACE_SYSCALL and display
592 * this execve call normally.
593 */
594 kill(getpid(), SIGSTOP);
595#endif /* !USE_PROCFS */
596
597 execv(pathname, argv);
598 perror("strace: exec");
599 _exit(1);
600 break;
601 }
602 default:
603 if ((tcp = alloctcb(pid)) == NULL) {
604 cleanup();
605 exit(1);
606 }
607#ifdef USE_PROCFS
608 if (proc_open(tcp, 0) < 0) {
609 fprintf(stderr, "trouble opening proc file\n");
610 cleanup();
611 exit(1);
612 }
613#endif /* USE_PROCFS */
614 break;
615 }
616}
617
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618int
619main(argc, argv)
620int argc;
621char *argv[];
622{
623 extern int optind;
624 extern char *optarg;
625 struct tcb *tcp;
626 int c, pid = 0;
627 struct sigaction sa;
628
629 static char buf[BUFSIZ];
630
Roland McGrathee9d4352002-12-18 04:16:10 +0000631 /* Allocate the initial tcbtab. */
632 tcbtabsize = argc; /* Surely enough for all -p args. */
633 tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
634 tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
635 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
636 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
637
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000638 progname = argv[0];
639 outf = stderr;
640 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000641 set_sortby(DEFAULT_SORTBY);
642 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000643 qualify("trace=all");
644 qualify("abbrev=all");
645 qualify("verbose=all");
646 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000647 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000648 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649 switch (c) {
650 case 'c':
651 cflag++;
652 dtime++;
653 break;
654 case 'd':
655 debug++;
656 break;
657 case 'f':
658 followfork++;
659 break;
660 case 'F':
661 followvfork++;
662 break;
663 case 'h':
664 usage(stdout, 0);
665 break;
666 case 'i':
667 iflag++;
668 break;
669 case 'q':
670 qflag++;
671 break;
672 case 'r':
673 rflag++;
674 tflag++;
675 break;
676 case 't':
677 tflag++;
678 break;
679 case 'T':
680 dtime++;
681 break;
682 case 'x':
683 xflag++;
684 break;
685 case 'v':
686 qualify("abbrev=none");
687 break;
688 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000689 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690 exit(0);
691 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000692 case 'z':
693 not_failing_only = 1;
694 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 case 'a':
696 acolumn = atoi(optarg);
697 break;
698 case 'e':
699 qualify(optarg);
700 break;
701 case 'o':
702 outfname = strdup(optarg);
703 break;
704 case 'O':
705 set_overhead(atoi(optarg));
706 break;
707 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000708 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709 fprintf(stderr, "%s: Invalid process id: %s\n",
710 progname, optarg);
711 break;
712 }
713 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000714 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 break;
716 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000717 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000718 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 progname);
720 exit(1);
721 }
722 tcp->flags |= TCB_ATTACHED;
723 pflag_seen++;
724 break;
725 case 's':
726 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000727 if (max_strlen < 0) {
728 fprintf(stderr,
729 "%s: invalid -s argument: %s\n",
730 progname, optarg);
731 exit(1);
732 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733 break;
734 case 'S':
735 set_sortby(optarg);
736 break;
737 case 'u':
738 username = strdup(optarg);
739 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000740 case 'E':
741 if (putenv(optarg) < 0) {
742 fprintf(stderr, "%s: out of memory\n",
743 progname);
744 exit(1);
745 }
746 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000747 default:
748 usage(stderr, 1);
749 break;
750 }
751 }
752
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000753 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000754 usage(stderr, 1);
755
Roland McGrathcb9def62006-04-25 07:48:03 +0000756 if (followfork > 1 && cflag) {
757 fprintf(stderr,
758 "%s: -c and -ff are mutually exclusive options\n",
759 progname);
760 exit(1);
761 }
762
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000763 /* See if they want to run as another user. */
764 if (username != NULL) {
765 struct passwd *pent;
766
767 if (getuid() != 0 || geteuid() != 0) {
768 fprintf(stderr,
769 "%s: you must be root to use the -u option\n",
770 progname);
771 exit(1);
772 }
773 if ((pent = getpwnam(username)) == NULL) {
774 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000775 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776 exit(1);
777 }
778 run_uid = pent->pw_uid;
779 run_gid = pent->pw_gid;
780 }
781 else {
782 run_uid = getuid();
783 run_gid = getgid();
784 }
785
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000786 /* Check if they want to redirect the output. */
787 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000788 /* See if they want to pipe the output. */
789 if (outfname[0] == '|' || outfname[0] == '!') {
790 /*
791 * We can't do the <outfname>.PID funny business
792 * when using popen, so prohibit it.
793 */
794 if (followfork > 1) {
795 fprintf(stderr, "\
796%s: piping the output and -ff are mutually exclusive options\n",
797 progname);
798 exit(1);
799 }
800
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000801 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000802 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000803 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000804 else if (followfork <= 1 &&
805 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000807 }
808
Roland McGrath37b9a662003-11-07 02:26:54 +0000809 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000810 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000811 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000813 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000814 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 sigemptyset(&empty_set);
817 sigemptyset(&blocked_set);
818 sa.sa_handler = SIG_IGN;
819 sigemptyset(&sa.sa_mask);
820 sa.sa_flags = 0;
821 sigaction(SIGTTOU, &sa, NULL);
822 sigaction(SIGTTIN, &sa, NULL);
823 if (interactive) {
824 sigaddset(&blocked_set, SIGHUP);
825 sigaddset(&blocked_set, SIGINT);
826 sigaddset(&blocked_set, SIGQUIT);
827 sigaddset(&blocked_set, SIGPIPE);
828 sigaddset(&blocked_set, SIGTERM);
829 sa.sa_handler = interrupt;
830#ifdef SUNOS4
831 /* POSIX signals on sunos4.1 are a little broken. */
832 sa.sa_flags = SA_INTERRUPT;
833#endif /* SUNOS4 */
834 }
835 sigaction(SIGHUP, &sa, NULL);
836 sigaction(SIGINT, &sa, NULL);
837 sigaction(SIGQUIT, &sa, NULL);
838 sigaction(SIGPIPE, &sa, NULL);
839 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000840#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000841 sa.sa_handler = reaper;
842 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000843#else
844 /* Make sure SIGCHLD has the default action so that waitpid
845 definitely works without losing track of children. The user
846 should not have given us a bogus state to inherit, but he might
847 have. Arguably we should detect SIG_IGN here and pass it on
848 to children, but probably noone really needs that. */
849 sa.sa_handler = SIG_DFL;
850 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000851#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000852
Roland McGrath02203312007-06-11 22:06:31 +0000853 if (pflag_seen)
854 startup_attach();
855 else
856 startup_child(&argv[optind]);
857
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 if (trace() < 0)
859 exit(1);
860 cleanup();
861 exit(0);
862}
863
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000864int
865expand_tcbtab()
866{
867 /* Allocate some more TCBs and expand the table.
868 We don't want to relocate the TCBs because our
869 callers have pointers and it would be a pain.
870 So tcbtab is a table of pointers. Since we never
871 free the TCBs, we allocate a single chunk of many. */
872 struct tcb **newtab = (struct tcb **)
873 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
874 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
875 sizeof *newtcbs);
876 int i;
877 if (newtab == NULL || newtcbs == NULL) {
878 if (newtab != NULL)
879 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000880 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
881 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000882 return 1;
883 }
884 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
885 newtab[i] = &newtcbs[i - tcbtabsize];
886 tcbtabsize *= 2;
887 tcbtab = newtab;
888
889 return 0;
890}
891
892
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000894alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895{
896 int i;
897 struct tcb *tcp;
898
Roland McGrathee9d4352002-12-18 04:16:10 +0000899 for (i = 0; i < tcbtabsize; i++) {
900 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 if ((tcp->flags & TCB_INUSE) == 0) {
902 tcp->pid = pid;
903 tcp->parent = NULL;
904 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000905 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000906#ifdef TCB_CLONE_THREAD
907 tcp->nclone_threads = tcp->nclone_detached = 0;
908 tcp->nclone_waiting = 0;
909#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910 tcp->flags = TCB_INUSE | TCB_STARTUP;
911 tcp->outf = outf; /* Initialise to current out file */
912 tcp->stime.tv_sec = 0;
913 tcp->stime.tv_usec = 0;
914 tcp->pfd = -1;
915 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000916 if (command_options_parsed)
917 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000918 return tcp;
919 }
920 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000921 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 return NULL;
923}
924
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000925#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926int
927proc_open(tcp, attaching)
928struct tcb *tcp;
929int attaching;
930{
931 char proc[32];
932 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000933#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000934 int i;
935 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936 sigset_t signals;
937 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000938#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939#ifndef HAVE_POLLABLE_PROCFS
940 static int last_pfd;
941#endif
942
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000943#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000944 /* Open the process pseudo-files in /proc. */
945 sprintf(proc, "/proc/%d/ctl", tcp->pid);
946 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947 perror("strace: open(\"/proc/...\", ...)");
948 return -1;
949 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000950 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 return -1;
952 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000953 sprintf(proc, "/proc/%d/status", tcp->pid);
954 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
955 perror("strace: open(\"/proc/...\", ...)");
956 return -1;
957 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000958 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000959 return -1;
960 }
961 sprintf(proc, "/proc/%d/as", tcp->pid);
962 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
963 perror("strace: open(\"/proc/...\", ...)");
964 return -1;
965 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000966 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000967 return -1;
968 }
969#else
970 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000971#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000972 sprintf(proc, "/proc/%d", tcp->pid);
973 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000974#else /* FREEBSD */
975 sprintf(proc, "/proc/%d/mem", tcp->pid);
976 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
977#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000978 perror("strace: open(\"/proc/...\", ...)");
979 return -1;
980 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000981 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000982 return -1;
983 }
984#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000985#ifdef FREEBSD
986 sprintf(proc, "/proc/%d/regs", tcp->pid);
987 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
988 perror("strace: open(\"/proc/.../regs\", ...)");
989 return -1;
990 }
991 if (cflag) {
992 sprintf(proc, "/proc/%d/status", tcp->pid);
993 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
994 perror("strace: open(\"/proc/.../status\", ...)");
995 return -1;
996 }
997 } else
998 tcp->pfd_status = -1;
999#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001000 rebuild_pollv();
1001 if (!attaching) {
1002 /*
1003 * Wait for the child to pause. Because of a race
1004 * condition we have to poll for the event.
1005 */
1006 for (;;) {
1007 if (IOCTL_STATUS (tcp) < 0) {
1008 perror("strace: PIOCSTATUS");
1009 return -1;
1010 }
1011 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001012 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001013 }
1014 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001015#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001016 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001017 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001018 perror("strace: PIOCSTOP");
1019 return -1;
1020 }
Roland McGrath553a6092002-12-16 20:40:39 +00001021#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022#ifdef PIOCSET
1023 /* Set Run-on-Last-Close. */
1024 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001025 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 perror("PIOCSET PR_RLC");
1027 return -1;
1028 }
1029 /* Set or Reset Inherit-on-Fork. */
1030 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001031 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 perror("PIOC{SET,RESET} PR_FORK");
1033 return -1;
1034 }
1035#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001036#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1038 perror("PIOCSRLC");
1039 return -1;
1040 }
1041 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1042 perror("PIOC{S,R}FORK");
1043 return -1;
1044 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001045#else /* FREEBSD */
1046 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1047 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1048 perror("PIOCGFL");
1049 return -1;
1050 }
1051 arg &= ~PF_LINGER;
1052 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1053 perror("PIOCSFL");
1054 return -1;
1055 }
1056#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001058#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001059 /* Enable all syscall entries we care about. */
1060 premptyset(&syscalls);
1061 for (i = 1; i < MAX_QUALS; ++i) {
1062 if (i > (sizeof syscalls) * CHAR_BIT) break;
1063 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1064 }
1065 praddset (&syscalls, SYS_execve);
1066 if (followfork) {
1067 praddset (&syscalls, SYS_fork);
1068#ifdef SYS_forkall
1069 praddset (&syscalls, SYS_forkall);
1070#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001071#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001072 praddset (&syscalls, SYS_fork1);
1073#endif
1074#ifdef SYS_rfork1
1075 praddset (&syscalls, SYS_rfork1);
1076#endif
1077#ifdef SYS_rforkall
1078 praddset (&syscalls, SYS_rforkall);
1079#endif
1080 }
1081 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 perror("PIOCSENTRY");
1083 return -1;
1084 }
John Hughes19e49982001-10-19 08:59:12 +00001085 /* Enable the syscall exits. */
1086 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 perror("PIOSEXIT");
1088 return -1;
1089 }
John Hughes19e49982001-10-19 08:59:12 +00001090 /* Enable signals we care about. */
1091 premptyset(&signals);
1092 for (i = 1; i < MAX_QUALS; ++i) {
1093 if (i > (sizeof signals) * CHAR_BIT) break;
1094 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1095 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001096 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097 perror("PIOCSTRACE");
1098 return -1;
1099 }
John Hughes19e49982001-10-19 08:59:12 +00001100 /* Enable faults we care about */
1101 premptyset(&faults);
1102 for (i = 1; i < MAX_QUALS; ++i) {
1103 if (i > (sizeof faults) * CHAR_BIT) break;
1104 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1105 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001106 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 perror("PIOCSFAULT");
1108 return -1;
1109 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001110#else /* FREEBSD */
1111 /* set events flags. */
1112 arg = S_SIG | S_SCE | S_SCX ;
1113 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1114 perror("PIOCBIS");
1115 return -1;
1116 }
1117#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 if (!attaching) {
1119#ifdef MIPS
1120 /*
1121 * The SGI PRSABORT doesn't work for pause() so
1122 * we send it a caught signal to wake it up.
1123 */
1124 kill(tcp->pid, SIGINT);
1125#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001126#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001127 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001128 arg = PRSABORT;
1129 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130 perror("PIOCRUN");
1131 return -1;
1132 }
Roland McGrath553a6092002-12-16 20:40:39 +00001133#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001134#endif /* !MIPS*/
1135#ifdef FREEBSD
1136 /* wake up the child if it received the SIGSTOP */
1137 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001138#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 for (;;) {
1140 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001141 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142 perror("PIOCWSTOP");
1143 return -1;
1144 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001145 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001146 tcp->flags &= ~TCB_INSYSCALL;
1147 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001148 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 break;
1150 }
1151 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001152#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001153 arg = 0;
1154 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001155#else /* FREEBSD */
1156 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001157#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 perror("PIOCRUN");
1159 return -1;
1160 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001161#ifdef FREEBSD
1162 /* handle the case where we "opened" the child before
1163 it did the kill -STOP */
1164 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1165 tcp->status.PR_WHAT == SIGSTOP)
1166 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001167#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001169#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001171#else /* FREEBSD */
1172 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001173 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001174 /* We are attaching to an already running process.
1175 * Try to figure out the state of the process in syscalls,
1176 * to handle the first event well.
1177 * This is done by having a look at the "wchan" property of the
1178 * process, which tells where it is stopped (if it is). */
1179 FILE * status;
1180 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001181
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001182 sprintf(proc, "/proc/%d/status", tcp->pid);
1183 status = fopen(proc, "r");
1184 if (status &&
1185 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1186 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1187 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1188 strcmp(wchan, "stopevent")) {
1189 /* The process is asleep in the middle of a syscall.
1190 Fake the syscall entry event */
1191 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1192 tcp->status.PR_WHY = PR_SYSENTRY;
1193 trace_syscall(tcp);
1194 }
1195 if (status)
1196 fclose(status);
1197 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001198 }
1199#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200#ifndef HAVE_POLLABLE_PROCFS
1201 if (proc_poll_pipe[0] != -1)
1202 proc_poller(tcp->pfd);
1203 else if (nprocs > 1) {
1204 proc_poll_open();
1205 proc_poller(last_pfd);
1206 proc_poller(tcp->pfd);
1207 }
1208 last_pfd = tcp->pfd;
1209#endif /* !HAVE_POLLABLE_PROCFS */
1210 return 0;
1211}
1212
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001213#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001215struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216pid2tcb(pid)
1217int pid;
1218{
1219 int i;
1220 struct tcb *tcp;
1221
Roland McGrathee9d4352002-12-18 04:16:10 +00001222 for (i = 0; i < tcbtabsize; i++) {
1223 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 if (pid && tcp->pid != pid)
1225 continue;
1226 if (tcp->flags & TCB_INUSE)
1227 return tcp;
1228 }
1229 return NULL;
1230}
1231
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001232#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233
1234static struct tcb *
1235pfd2tcb(pfd)
1236int pfd;
1237{
1238 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239
Roland McGrathca16be82003-01-10 19:55:28 +00001240 for (i = 0; i < tcbtabsize; i++) {
1241 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 if (tcp->pfd != pfd)
1243 continue;
1244 if (tcp->flags & TCB_INUSE)
1245 return tcp;
1246 }
1247 return NULL;
1248}
1249
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001250#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251
1252void
1253droptcb(tcp)
1254struct tcb *tcp;
1255{
1256 if (tcp->pid == 0)
1257 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001258#ifdef TCB_CLONE_THREAD
1259 if (tcp->nclone_threads > 0) {
1260 /* There are other threads left in this process, but this
1261 is the one whose PID represents the whole process.
1262 We need to keep this record around as a zombie until
1263 all the threads die. */
1264 tcp->flags |= TCB_EXITING;
1265 return;
1266 }
1267#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268 nprocs--;
1269 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001270
Roland McGrathe29341c2003-01-10 20:14:20 +00001271 if (tcp->parent != NULL) {
1272 tcp->parent->nchildren--;
1273#ifdef TCB_CLONE_THREAD
1274 if (tcp->flags & TCB_CLONE_DETACHED)
1275 tcp->parent->nclone_detached--;
1276 if (tcp->flags & TCB_CLONE_THREAD)
1277 tcp->parent->nclone_threads--;
1278#endif
Roland McGrath09623452003-05-23 02:27:13 +00001279#ifdef TCB_CLONE_DETACHED
1280 if (!(tcp->flags & TCB_CLONE_DETACHED))
1281#endif
1282 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001283 tcp->parent = NULL;
1284 }
1285
1286 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287 if (tcp->pfd != -1) {
1288 close(tcp->pfd);
1289 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001290#ifdef FREEBSD
1291 if (tcp->pfd_reg != -1) {
1292 close(tcp->pfd_reg);
1293 tcp->pfd_reg = -1;
1294 }
1295 if (tcp->pfd_status != -1) {
1296 close(tcp->pfd_status);
1297 tcp->pfd_status = -1;
1298 }
Roland McGrath553a6092002-12-16 20:40:39 +00001299#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001300#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001301 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302#endif
1303 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001304
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001305 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001307
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001308 tcp->outf = 0;
1309}
1310
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001311#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312
1313static int
1314resume(tcp)
1315struct tcb *tcp;
1316{
1317 if (tcp == NULL)
1318 return -1;
1319
1320 if (!(tcp->flags & TCB_SUSPENDED)) {
1321 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1322 return -1;
1323 }
1324 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001325#ifdef TCB_CLONE_THREAD
1326 if (tcp->flags & TCB_CLONE_THREAD)
1327 tcp->parent->nclone_waiting--;
1328#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329
1330 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1331 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1332 return -1;
1333 }
1334
1335 if (!qflag)
1336 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1337 return 0;
1338}
1339
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001340#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341
Roland McGrath0a463882007-07-05 18:43:16 +00001342/* detach traced process; continue with sig
1343 Never call DETACH twice on the same process as both unattached and
1344 attached-unstopped processes give the same ESRCH. For unattached process we
1345 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346
1347static int
1348detach(tcp, sig)
1349struct tcb *tcp;
1350int sig;
1351{
1352 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001353#ifdef LINUX
Roland McGrath02203312007-06-11 22:06:31 +00001354 int status, resumed, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001355 struct tcb *zombie = NULL;
1356
1357 /* If the group leader is lingering only because of this other
1358 thread now dying, then detach the leader as well. */
1359 if ((tcp->flags & TCB_CLONE_THREAD) &&
1360 tcp->parent->nclone_threads == 1 &&
1361 (tcp->parent->flags & TCB_EXITING))
1362 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001363#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364
1365 if (tcp->flags & TCB_BPTSET)
1366 sig = SIGKILL;
1367
1368#ifdef LINUX
1369 /*
1370 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001371 * before detaching. Arghh. We go through hoops
1372 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001374#if defined(SPARC)
1375#undef PTRACE_DETACH
1376#define PTRACE_DETACH PTRACE_SUNDETACH
1377#endif
Roland McGrath02203312007-06-11 22:06:31 +00001378 /*
1379 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1380 * expected SIGSTOP. We must catch exactly one as otherwise the
1381 * detached process would be left stopped (process state T).
1382 */
1383 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1385 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001386 }
1387 else if (errno != ESRCH) {
1388 /* Shouldn't happen. */
1389 perror("detach: ptrace(PTRACE_DETACH, ...)");
1390 }
Roland McGrath134813a2007-06-02 00:07:33 +00001391 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1392 : tcp->pid),
1393 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001394 if (errno != ESRCH)
1395 perror("detach: checking sanity");
1396 }
Roland McGrath02203312007-06-11 22:06:31 +00001397 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1398 ? tcp->parent->pid : tcp->pid),
1399 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001400 if (errno != ESRCH)
1401 perror("detach: stopping child");
1402 }
Roland McGrath02203312007-06-11 22:06:31 +00001403 else
1404 catch_sigstop = 1;
1405 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001407#ifdef __WALL
1408 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1409 if (errno == ECHILD) /* Already gone. */
1410 break;
1411 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001412 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001413 break;
1414 }
1415#endif /* __WALL */
1416 /* No __WALL here. */
1417 if (waitpid(tcp->pid, &status, 0) < 0) {
1418 if (errno != ECHILD) {
1419 perror("detach: waiting");
1420 break;
1421 }
1422#ifdef __WCLONE
1423 /* If no processes, try clones. */
1424 if (wait4(tcp->pid, &status, __WCLONE,
1425 NULL) < 0) {
1426 if (errno != ECHILD)
1427 perror("detach: waiting");
1428 break;
1429 }
1430#endif /* __WCLONE */
1431 }
1432#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001433 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001434#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 if (!WIFSTOPPED(status)) {
1436 /* Au revoir, mon ami. */
1437 break;
1438 }
1439 if (WSTOPSIG(status) == SIGSTOP) {
1440 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001441 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 if (errno != ESRCH)
1443 perror("detach: ptrace(PTRACE_DETACH, ...)");
1444 /* I died trying. */
1445 }
1446 break;
1447 }
1448 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001449 WSTOPSIG(status) == SIGTRAP ?
1450 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 if (errno != ESRCH)
1452 perror("detach: ptrace(PTRACE_CONT, ...)");
1453 break;
1454 }
1455 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001456#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457
1458#if defined(SUNOS4)
1459 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1460 if (sig && kill(tcp->pid, sig) < 0)
1461 perror("detach: kill");
1462 sig = 0;
1463 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1464 perror("detach: ptrace(PTRACE_DETACH, ...)");
1465#endif /* SUNOS4 */
1466
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001467#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001468 resumed = 0;
1469
1470 /* XXX This won't always be quite right (but it never was).
1471 A waiter with argument 0 or < -1 is waiting for any pid in
1472 a particular pgrp, which this child might or might not be
1473 in. The waiter will only wake up if it's argument is -1
1474 or if it's waiting for tcp->pid's pgrp. It makes a
1475 difference to wake up a waiter when there might be more
1476 traced children, because it could get a false ECHILD
1477 error. OTOH, if this was the last child in the pgrp, then
1478 it ought to wake up and get ECHILD. We would have to
1479 search the system for all pid's in the pgrp to be sure.
1480
1481 && (t->waitpid == -1 ||
1482 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1483 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1484 */
1485
1486 if (tcp->parent &&
1487 (tcp->parent->flags & TCB_SUSPENDED) &&
1488 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1489 error = resume(tcp->parent);
1490 ++resumed;
1491 }
1492#ifdef TCB_CLONE_THREAD
1493 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1494 /* Some other threads of our parent are waiting too. */
1495 unsigned int i;
1496
1497 /* Resume all the threads that were waiting for this PID. */
1498 for (i = 0; i < tcbtabsize; i++) {
1499 struct tcb *t = tcbtab[i];
1500 if (t->parent == tcp->parent && t != tcp
1501 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1502 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1503 && t->waitpid == tcp->pid) {
1504 error |= resume (t);
1505 ++resumed;
1506 }
1507 }
1508 if (resumed == 0)
1509 /* Noone was waiting for this PID in particular,
1510 so now we might need to resume some wildcarders. */
1511 for (i = 0; i < tcbtabsize; i++) {
1512 struct tcb *t = tcbtab[i];
1513 if (t->parent == tcp->parent && t != tcp
1514 && ((t->flags
1515 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1516 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1517 && t->waitpid <= 0
1518 ) {
1519 error |= resume (t);
1520 break;
1521 }
1522 }
1523 }
1524#endif
1525
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001526#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527
1528 if (!qflag)
1529 fprintf(stderr, "Process %u detached\n", tcp->pid);
1530
1531 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001532
1533#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001534 if (zombie != NULL) {
1535 /* TCP no longer exists therefore you must not detach () it. */
1536 droptcb(zombie);
1537 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001538#endif
1539
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 return error;
1541}
1542
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001543#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544
1545static void
1546reaper(sig)
1547int sig;
1548{
1549 int pid;
1550 int status;
1551
1552 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1553#if 0
1554 struct tcb *tcp;
1555
1556 tcp = pid2tcb(pid);
1557 if (tcp)
1558 droptcb(tcp);
1559#endif
1560 }
1561}
1562
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001563#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564
1565static void
1566cleanup()
1567{
1568 int i;
1569 struct tcb *tcp;
1570
Roland McGrathee9d4352002-12-18 04:16:10 +00001571 for (i = 0; i < tcbtabsize; i++) {
1572 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573 if (!(tcp->flags & TCB_INUSE))
1574 continue;
1575 if (debug)
1576 fprintf(stderr,
1577 "cleanup: looking at pid %u\n", tcp->pid);
1578 if (tcp_last &&
1579 (!outfname || followfork < 2 || tcp_last == tcp)) {
1580 tprintf(" <unfinished ...>\n");
1581 tcp_last = NULL;
1582 }
1583 if (tcp->flags & TCB_ATTACHED)
1584 detach(tcp, 0);
1585 else {
1586 kill(tcp->pid, SIGCONT);
1587 kill(tcp->pid, SIGTERM);
1588 }
1589 }
1590 if (cflag)
1591 call_summary(outf);
1592}
1593
1594static void
1595interrupt(sig)
1596int sig;
1597{
1598 interrupted = 1;
1599}
1600
1601#ifndef HAVE_STRERROR
1602
Roland McGrath6d2b3492002-12-30 00:51:30 +00001603#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604extern int sys_nerr;
1605extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001606#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607
1608const char *
1609strerror(errno)
1610int errno;
1611{
1612 static char buf[64];
1613
1614 if (errno < 1 || errno >= sys_nerr) {
1615 sprintf(buf, "Unknown error %d", errno);
1616 return buf;
1617 }
1618 return sys_errlist[errno];
1619}
1620
1621#endif /* HAVE_STERRROR */
1622
1623#ifndef HAVE_STRSIGNAL
1624
Roland McGrath8f474e02003-01-14 07:53:33 +00001625#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001626extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001628#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1629extern char *_sys_siglist[];
1630#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631
1632const char *
1633strsignal(sig)
1634int sig;
1635{
1636 static char buf[64];
1637
1638 if (sig < 1 || sig >= NSIG) {
1639 sprintf(buf, "Unknown signal %d", sig);
1640 return buf;
1641 }
1642#ifdef HAVE__SYS_SIGLIST
1643 return _sys_siglist[sig];
1644#else
1645 return sys_siglist[sig];
1646#endif
1647}
1648
1649#endif /* HAVE_STRSIGNAL */
1650
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001651#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652
1653static void
1654rebuild_pollv()
1655{
1656 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657
Roland McGrathee9d4352002-12-18 04:16:10 +00001658 if (pollv != NULL)
1659 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001660 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001661 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001662 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001663 exit(1);
1664 }
1665
Roland McGrathca16be82003-01-10 19:55:28 +00001666 for (i = j = 0; i < tcbtabsize; i++) {
1667 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 if (!(tcp->flags & TCB_INUSE))
1669 continue;
1670 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001671 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672 j++;
1673 }
1674 if (j != nprocs) {
1675 fprintf(stderr, "strace: proc miscount\n");
1676 exit(1);
1677 }
1678}
1679
1680#ifndef HAVE_POLLABLE_PROCFS
1681
1682static void
1683proc_poll_open()
1684{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 int i;
1686
1687 if (pipe(proc_poll_pipe) < 0) {
1688 perror("pipe");
1689 exit(1);
1690 }
1691 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001692 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 exit(1);
1694 }
1695 }
1696}
1697
1698static int
1699proc_poll(pollv, nfds, timeout)
1700struct pollfd *pollv;
1701int nfds;
1702int timeout;
1703{
1704 int i;
1705 int n;
1706 struct proc_pollfd pollinfo;
1707
1708 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1709 return n;
1710 if (n != sizeof(struct proc_pollfd)) {
1711 fprintf(stderr, "panic: short read: %d\n", n);
1712 exit(1);
1713 }
1714 for (i = 0; i < nprocs; i++) {
1715 if (pollv[i].fd == pollinfo.fd)
1716 pollv[i].revents = pollinfo.revents;
1717 else
1718 pollv[i].revents = 0;
1719 }
1720 poller_pid = pollinfo.pid;
1721 return 1;
1722}
1723
1724static void
1725wakeup_handler(sig)
1726int sig;
1727{
1728}
1729
1730static void
1731proc_poller(pfd)
1732int pfd;
1733{
1734 struct proc_pollfd pollinfo;
1735 struct sigaction sa;
1736 sigset_t blocked_set, empty_set;
1737 int i;
1738 int n;
1739 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001740#ifdef FREEBSD
1741 struct procfs_status pfs;
1742#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743
1744 switch (fork()) {
1745 case -1:
1746 perror("fork");
1747 _exit(0);
1748 case 0:
1749 break;
1750 default:
1751 return;
1752 }
1753
1754 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1755 sa.sa_flags = 0;
1756 sigemptyset(&sa.sa_mask);
1757 sigaction(SIGHUP, &sa, NULL);
1758 sigaction(SIGINT, &sa, NULL);
1759 sigaction(SIGQUIT, &sa, NULL);
1760 sigaction(SIGPIPE, &sa, NULL);
1761 sigaction(SIGTERM, &sa, NULL);
1762 sa.sa_handler = wakeup_handler;
1763 sigaction(SIGUSR1, &sa, NULL);
1764 sigemptyset(&blocked_set);
1765 sigaddset(&blocked_set, SIGUSR1);
1766 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1767 sigemptyset(&empty_set);
1768
1769 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1770 perror("getrlimit(RLIMIT_NOFILE, ...)");
1771 _exit(0);
1772 }
1773 n = rl.rlim_cur;
1774 for (i = 0; i < n; i++) {
1775 if (i != pfd && i != proc_poll_pipe[1])
1776 close(i);
1777 }
1778
1779 pollinfo.fd = pfd;
1780 pollinfo.pid = getpid();
1781 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001782#ifndef FREEBSD
1783 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1784#else /* FREEBSD */
1785 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1786#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001787 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 switch (errno) {
1789 case EINTR:
1790 continue;
1791 case EBADF:
1792 pollinfo.revents = POLLERR;
1793 break;
1794 case ENOENT:
1795 pollinfo.revents = POLLHUP;
1796 break;
1797 default:
1798 perror("proc_poller: PIOCWSTOP");
1799 }
1800 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1801 _exit(0);
1802 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001803 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1805 sigsuspend(&empty_set);
1806 }
1807}
1808
1809#endif /* !HAVE_POLLABLE_PROCFS */
1810
1811static int
1812choose_pfd()
1813{
1814 int i, j;
1815 struct tcb *tcp;
1816
1817 static int last;
1818
1819 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001820 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821 /*
1822 * The previous process is ready to run again. We'll
1823 * let it do so if it is currently in a syscall. This
1824 * heuristic improves the readability of the trace.
1825 */
1826 tcp = pfd2tcb(pollv[last].fd);
1827 if (tcp && (tcp->flags & TCB_INSYSCALL))
1828 return pollv[last].fd;
1829 }
1830
1831 for (i = 0; i < nprocs; i++) {
1832 /* Let competing children run round robin. */
1833 j = (i + last + 1) % nprocs;
1834 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1835 tcp = pfd2tcb(pollv[j].fd);
1836 if (!tcp) {
1837 fprintf(stderr, "strace: lost proc\n");
1838 exit(1);
1839 }
1840 droptcb(tcp);
1841 return -1;
1842 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001843 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844 last = j;
1845 return pollv[j].fd;
1846 }
1847 }
1848 fprintf(stderr, "strace: nothing ready\n");
1849 exit(1);
1850}
1851
1852static int
1853trace()
1854{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001855#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001856 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001857#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001858 struct tcb *tcp;
1859 int pfd;
1860 int what;
1861 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001862 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863
1864 for (;;) {
1865 if (interactive)
1866 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1867
1868 if (nprocs == 0)
1869 break;
1870
1871 switch (nprocs) {
1872 case 1:
1873#ifndef HAVE_POLLABLE_PROCFS
1874 if (proc_poll_pipe[0] == -1) {
1875#endif
1876 tcp = pid2tcb(0);
1877 if (!tcp)
1878 continue;
1879 pfd = tcp->pfd;
1880 if (pfd == -1)
1881 continue;
1882 break;
1883#ifndef HAVE_POLLABLE_PROCFS
1884 }
1885 /* fall through ... */
1886#endif /* !HAVE_POLLABLE_PROCFS */
1887 default:
1888#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001889#ifdef POLL_HACK
1890 /* On some systems (e.g. UnixWare) we get too much ugly
1891 "unfinished..." stuff when multiple proceses are in
1892 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001893
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001894 if (in_syscall) {
1895 struct pollfd pv;
1896 tcp = in_syscall;
1897 in_syscall = NULL;
1898 pv.fd = tcp->pfd;
1899 pv.events = POLLWANT;
1900 if ((what = poll (&pv, 1, 1)) < 0) {
1901 if (interrupted)
1902 return 0;
1903 continue;
1904 }
1905 else if (what == 1 && pv.revents & POLLWANT) {
1906 goto FOUND;
1907 }
1908 }
1909#endif
1910
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 if (poll(pollv, nprocs, INFTIM) < 0) {
1912 if (interrupted)
1913 return 0;
1914 continue;
1915 }
1916#else /* !HAVE_POLLABLE_PROCFS */
1917 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1918 if (interrupted)
1919 return 0;
1920 continue;
1921 }
1922#endif /* !HAVE_POLLABLE_PROCFS */
1923 pfd = choose_pfd();
1924 if (pfd == -1)
1925 continue;
1926 break;
1927 }
1928
1929 /* Look up `pfd' in our table. */
1930 if ((tcp = pfd2tcb(pfd)) == NULL) {
1931 fprintf(stderr, "unknown pfd: %u\n", pfd);
1932 exit(1);
1933 }
John Hughesb6643082002-05-23 11:02:22 +00001934#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001935 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001936#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937 /* Get the status of the process. */
1938 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001939#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001940 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001941#else /* FREEBSD */
1942 /* Thanks to some scheduling mystery, the first poller
1943 sometimes waits for the already processed end of fork
1944 event. Doing a non blocking poll here solves the problem. */
1945 if (proc_poll_pipe[0] != -1)
1946 ioctl_result = IOCTL_STATUS (tcp);
1947 else
1948 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001949#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 ioctl_errno = errno;
1951#ifndef HAVE_POLLABLE_PROCFS
1952 if (proc_poll_pipe[0] != -1) {
1953 if (ioctl_result < 0)
1954 kill(poller_pid, SIGKILL);
1955 else
1956 kill(poller_pid, SIGUSR1);
1957 }
1958#endif /* !HAVE_POLLABLE_PROCFS */
1959 }
1960 if (interrupted)
1961 return 0;
1962
1963 if (interactive)
1964 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1965
1966 if (ioctl_result < 0) {
1967 /* Find out what happened if it failed. */
1968 switch (ioctl_errno) {
1969 case EINTR:
1970 case EBADF:
1971 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001972#ifdef FREEBSD
1973 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001974#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 case ENOENT:
1976 droptcb(tcp);
1977 continue;
1978 default:
1979 perror("PIOCWSTOP");
1980 exit(1);
1981 }
1982 }
1983
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001984#ifdef FREEBSD
1985 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1986 /* discard first event for a syscall we never entered */
1987 IOCTL (tcp->pfd, PIOCRUN, 0);
1988 continue;
1989 }
Roland McGrath553a6092002-12-16 20:40:39 +00001990#endif
1991
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001992 /* clear the just started flag */
1993 tcp->flags &= ~TCB_STARTUP;
1994
1995 /* set current output file */
1996 outf = tcp->outf;
1997
1998 if (cflag) {
1999 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002000#ifdef FREEBSD
2001 char buf[1024];
2002 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002004 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2005 buf[len] = '\0';
2006 sscanf(buf,
2007 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2008 &stime.tv_sec, &stime.tv_usec);
2009 } else
2010 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002011#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2013 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002014#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2016 tcp->stime = stime;
2017 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002018 what = tcp->status.PR_WHAT;
2019 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002020#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002022 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2023 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 if (trace_syscall(tcp) < 0) {
2025 fprintf(stderr, "syscall trouble\n");
2026 exit(1);
2027 }
2028 }
2029 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002030#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002032#ifdef POLL_HACK
2033 in_syscall = tcp;
2034#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 case PR_SYSEXIT:
2036 if (trace_syscall(tcp) < 0) {
2037 fprintf(stderr, "syscall trouble\n");
2038 exit(1);
2039 }
2040 break;
2041 case PR_SIGNALLED:
2042 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2043 printleader(tcp);
2044 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002045 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002047#ifdef PR_INFO
2048 if (tcp->status.PR_INFO.si_signo == what) {
2049 printleader(tcp);
2050 tprintf(" siginfo=");
2051 printsiginfo(&tcp->status.PR_INFO, 1);
2052 printtrailer(tcp);
2053 }
2054#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 }
2056 break;
2057 case PR_FAULTED:
2058 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2059 printleader(tcp);
2060 tprintf("=== FAULT %d ===", what);
2061 printtrailer(tcp);
2062 }
2063 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002064#ifdef FREEBSD
2065 case 0: /* handle case we polled for nothing */
2066 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002067#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002069 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 exit(1);
2071 break;
2072 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002073 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002074#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002075 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002076#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002077 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002078#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 perror("PIOCRUN");
2080 exit(1);
2081 }
2082 }
2083 return 0;
2084}
2085
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002086#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002087
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002088#ifdef TCB_GROUP_EXITING
2089/* Handle an exit detach or death signal that is taking all the
2090 related clone threads with it. This is called in three circumstances:
2091 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2092 SIG == 0 Continuing TCP will perform an exit_group syscall.
2093 SIG == other Continuing TCP with SIG will kill the process.
2094*/
2095static int
2096handle_group_exit(struct tcb *tcp, int sig)
2097{
2098 /* We need to locate our records of all the clone threads
2099 related to TCP, either its children or siblings. */
2100 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2101 ? tcp->parent
2102 : tcp->nclone_detached > 0
2103 ? tcp : NULL);
2104
2105 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002106 if (leader != NULL && leader != tcp &&
2107 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002108 fprintf(stderr,
2109 "PANIC: handle_group_exit: %d leader %d\n",
2110 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002111 /* TCP no longer exists therefore you must not detach () it. */
2112 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002113 }
2114 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002115 /* Mark that we are taking the process down. */
2116 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002117 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002118 detach(tcp, sig);
Roland McGrath00dc13f2004-10-20 02:04:15 +00002119 if (leader != NULL && leader != tcp) {
Roland McGrath0a463882007-07-05 18:43:16 +00002120 if ((leader->flags & TCB_ATTACHED) &&
2121 !(leader->flags & TCB_EXITING)) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00002122 /* We need to detach the leader so
2123 that the process death will be
Roland McGrathd6a32f12007-07-11 08:35:11 +00002124 reported to its real parent. */
Roland McGrath00dc13f2004-10-20 02:04:15 +00002125 if (debug)
2126 fprintf(stderr,
Roland McGrathd6a32f12007-07-11 08:35:11 +00002127 " [%d exit %d detaches %d]\n",
Roland McGrath00dc13f2004-10-20 02:04:15 +00002128 tcp->pid, sig, leader->pid);
2129 detach(leader, sig);
2130 }
2131 else
2132 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002133 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002134 }
2135 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2136 perror("strace: ptrace(PTRACE_CONT, ...)");
2137 cleanup();
2138 return -1;
2139 }
2140 else {
Roland McGrath05690952004-10-20 01:00:27 +00002141 if (leader != NULL)
2142 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002143 if (leader != NULL && leader != tcp)
2144 droptcb(tcp);
2145 /* The leader will report to us as parent now,
2146 and then we'll get to the SIG==-1 case. */
2147 return 0;
2148 }
2149 }
2150
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002151 return 0;
2152}
2153#endif
2154
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002155static int
2156trace()
2157{
2158 int pid;
2159 int wait_errno;
2160 int status;
2161 struct tcb *tcp;
2162#ifdef LINUX
2163 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002164#ifdef __WALL
2165 static int wait4_options = __WALL;
2166#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002167#endif /* LINUX */
2168
2169 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002170 if (interrupted)
2171 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172 if (interactive)
2173 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2174#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002175#ifdef __WALL
2176 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002177 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002178 /* this kernel does not support __WALL */
2179 wait4_options &= ~__WALL;
2180 errno = 0;
2181 pid = wait4(-1, &status, wait4_options,
2182 cflag ? &ru : NULL);
2183 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002184 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002185 /* most likely a "cloned" process */
2186 pid = wait4(-1, &status, __WCLONE,
2187 cflag ? &ru : NULL);
2188 if (pid == -1) {
2189 fprintf(stderr, "strace: clone wait4 "
2190 "failed: %s\n", strerror(errno));
2191 }
2192 }
2193#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002194 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002195#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196#endif /* LINUX */
2197#ifdef SUNOS4
2198 pid = wait(&status);
2199#endif /* SUNOS4 */
2200 wait_errno = errno;
2201 if (interactive)
2202 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2203
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204 if (pid == -1) {
2205 switch (wait_errno) {
2206 case EINTR:
2207 continue;
2208 case ECHILD:
2209 /*
2210 * We would like to verify this case
2211 * but sometimes a race in Solbourne's
2212 * version of SunOS sometimes reports
2213 * ECHILD before sending us SIGCHILD.
2214 */
2215#if 0
2216 if (nprocs == 0)
2217 return 0;
2218 fprintf(stderr, "strace: proc miscount\n");
2219 exit(1);
2220#endif
2221 return 0;
2222 default:
2223 errno = wait_errno;
2224 perror("strace: wait");
2225 return -1;
2226 }
2227 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002228 if (pid == popen_pid) {
2229 if (WIFEXITED(status) || WIFSIGNALED(status))
2230 popen_pid = -1;
2231 continue;
2232 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 if (debug)
2234 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2235
2236 /* Look up `pid' in our table. */
2237 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002238#ifdef LINUX
2239 if (followfork || followvfork) {
2240 /* This is needed to go with the CLONE_PTRACE
2241 changes in process.c/util.c: we might see
2242 the child's initial trap before we see the
2243 parent return from the clone syscall.
2244 Leave the child suspended until the parent
2245 returns from its system call. Only then
2246 will we have the association of parent and
2247 child so that we know how to do clearbpt
2248 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002249 if (nprocs == tcbtabsize &&
2250 expand_tcbtab())
2251 tcp = NULL;
2252 else
2253 tcp = alloctcb(pid);
2254 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002255 kill(pid, SIGKILL); /* XXX */
2256 return 0;
2257 }
2258 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002259 if (!qflag)
2260 fprintf(stderr, "\
2261Process %d attached (waiting for parent)\n",
2262 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002263 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002264 else
2265 /* This can happen if a clone call used
2266 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002267#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002268 {
2269 fprintf(stderr, "unknown pid: %u\n", pid);
2270 if (WIFSTOPPED(status))
2271 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2272 exit(1);
2273 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274 }
2275 /* set current output file */
2276 outf = tcp->outf;
2277 if (cflag) {
2278#ifdef LINUX
2279 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2280 tcp->stime = ru.ru_stime;
2281#endif /* !LINUX */
2282 }
2283
2284 if (tcp->flags & TCB_SUSPENDED) {
2285 /*
2286 * Apparently, doing any ptrace() call on a stopped
2287 * process, provokes the kernel to report the process
2288 * status again on a subsequent wait(), even if the
2289 * process has not been actually restarted.
2290 * Since we have inspected the arguments of suspended
2291 * processes we end up here testing for this case.
2292 */
2293 continue;
2294 }
2295 if (WIFSIGNALED(status)) {
2296 if (!cflag
2297 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2298 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002299 tprintf("+++ killed by %s %s+++",
2300 signame(WTERMSIG(status)),
2301#ifdef WCOREDUMP
2302 WCOREDUMP(status) ? "(core dumped) " :
2303#endif
2304 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 printtrailer(tcp);
2306 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002307#ifdef TCB_GROUP_EXITING
2308 handle_group_exit(tcp, -1);
2309#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002310 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002311#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312 continue;
2313 }
2314 if (WIFEXITED(status)) {
2315 if (debug)
2316 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002317 if ((tcp->flags & TCB_ATTACHED)
2318#ifdef TCB_GROUP_EXITING
2319 && !(tcp->parent && (tcp->parent->flags &
2320 TCB_GROUP_EXITING))
2321#endif
2322 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002323 fprintf(stderr,
2324 "PANIC: attached pid %u exited\n",
2325 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002326 if (tcp == tcp_last) {
2327 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2328 == TCB_INSYSCALL)
2329 tprintf(" <unfinished ... exit status %d>\n",
2330 WEXITSTATUS(status));
2331 tcp_last = NULL;
2332 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002333#ifdef TCB_GROUP_EXITING
2334 handle_group_exit(tcp, -1);
2335#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002337#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002338 continue;
2339 }
2340 if (!WIFSTOPPED(status)) {
2341 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2342 droptcb(tcp);
2343 continue;
2344 }
2345 if (debug)
2346 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002347 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348
Roland McGrath02203312007-06-11 22:06:31 +00002349 /*
2350 * Interestingly, the process may stop
2351 * with STOPSIG equal to some other signal
2352 * than SIGSTOP if we happend to attach
2353 * just before the process takes a signal.
2354 */
2355 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002356 /*
2357 * This flag is there to keep us in sync.
2358 * Next time this process stops it should
2359 * really be entering a system call.
2360 */
2361 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002362 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002363 /*
2364 * One example is a breakpoint inherited from
2365 * parent through fork ().
2366 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002367 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2368 droptcb(tcp);
2369 cleanup();
2370 return -1;
2371 }
2372 }
2373 goto tracing;
2374 }
2375
2376 if (WSTOPSIG(status) != SIGTRAP) {
2377 if (WSTOPSIG(status) == SIGSTOP &&
2378 (tcp->flags & TCB_SIGTRAPPED)) {
2379 /*
2380 * Trapped attempt to block SIGTRAP
2381 * Hope we are back in control now.
2382 */
2383 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2384 if (ptrace(PTRACE_SYSCALL,
2385 pid, (char *) 1, 0) < 0) {
2386 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2387 cleanup();
2388 return -1;
2389 }
2390 continue;
2391 }
2392 if (!cflag
2393 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002394 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002395#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002396# define PSR_RI 41
2397 struct siginfo si;
2398 unsigned long psr;
2399
2400 upeek(pid, PT_CR_IPSR, &psr);
2401 upeek(pid, PT_CR_IIP, &pc);
2402
2403 pc += (psr >> PSR_RI) & 0x3;
2404 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2405 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002406#elif defined PTRACE_GETSIGINFO
2407 if (WSTOPSIG(status) == SIGSEGV ||
2408 WSTOPSIG(status) == SIGBUS) {
2409 siginfo_t si;
2410 if (ptrace(PTRACE_GETSIGINFO, pid,
2411 0, &si) == 0)
2412 addr = (unsigned long)
2413 si.si_addr;
2414 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002415#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002416 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002417 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002418 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002419 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 printtrailer(tcp);
2421 }
Roland McGrath05690952004-10-20 01:00:27 +00002422 if (((tcp->flags & TCB_ATTACHED) ||
2423 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002425#ifdef TCB_GROUP_EXITING
2426 handle_group_exit(tcp, WSTOPSIG(status));
2427#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002429#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 continue;
2431 }
2432 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2433 WSTOPSIG(status)) < 0) {
2434 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2435 cleanup();
2436 return -1;
2437 }
2438 tcp->flags &= ~TCB_SUSPENDED;
2439 continue;
2440 }
Roland McGrath02203312007-06-11 22:06:31 +00002441 /* we handled the STATUS, we are permitted to interrupt now. */
2442 if (interrupted)
2443 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 if (trace_syscall(tcp) < 0) {
2445 if (tcp->flags & TCB_ATTACHED)
2446 detach(tcp, 0);
2447 else {
2448 ptrace(PTRACE_KILL,
2449 tcp->pid, (char *) 1, SIGTERM);
2450 droptcb(tcp);
2451 }
2452 continue;
2453 }
2454 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002455#ifdef TCB_GROUP_EXITING
2456 if (tcp->flags & TCB_GROUP_EXITING) {
2457 if (handle_group_exit(tcp, 0) < 0)
2458 return -1;
2459 continue;
2460 }
2461#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002462 if (tcp->flags & TCB_ATTACHED)
2463 detach(tcp, 0);
2464 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2465 perror("strace: ptrace(PTRACE_CONT, ...)");
2466 cleanup();
2467 return -1;
2468 }
2469 continue;
2470 }
2471 if (tcp->flags & TCB_SUSPENDED) {
2472 if (!qflag)
2473 fprintf(stderr, "Process %u suspended\n", pid);
2474 continue;
2475 }
2476 tracing:
2477 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2478 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2479 cleanup();
2480 return -1;
2481 }
2482 }
2483 return 0;
2484}
2485
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002486#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487
2488static int curcol;
2489
2490#ifdef __STDC__
2491#include <stdarg.h>
2492#define VA_START(a, b) va_start(a, b)
2493#else
2494#include <varargs.h>
2495#define VA_START(a, b) va_start(a)
2496#endif
2497
2498void
2499#ifdef __STDC__
2500tprintf(const char *fmt, ...)
2501#else
2502tprintf(fmt, va_alist)
2503char *fmt;
2504va_dcl
2505#endif
2506{
2507 va_list args;
2508
2509 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002510 if (outf) {
2511 int n = vfprintf(outf, fmt, args);
2512 if (n < 0 && outf != stderr)
2513 perror(outfname == NULL
2514 ? "<writing to pipe>" : outfname);
2515 else
2516 curcol += n;
2517 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002518 va_end(args);
2519 return;
2520}
2521
2522void
2523printleader(tcp)
2524struct tcb *tcp;
2525{
2526 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2527 tcp_last->flags |= TCB_REPRINT;
2528 tprintf(" <unfinished ...>\n");
2529 }
2530 curcol = 0;
2531 if ((followfork == 1 || pflag_seen > 1) && outfname)
2532 tprintf("%-5d ", tcp->pid);
2533 else if (nprocs > 1 && !outfname)
2534 tprintf("[pid %5u] ", tcp->pid);
2535 if (tflag) {
2536 char str[sizeof("HH:MM:SS")];
2537 struct timeval tv, dtv;
2538 static struct timeval otv;
2539
2540 gettimeofday(&tv, NULL);
2541 if (rflag) {
2542 if (otv.tv_sec == 0)
2543 otv = tv;
2544 tv_sub(&dtv, &tv, &otv);
2545 tprintf("%6ld.%06ld ",
2546 (long) dtv.tv_sec, (long) dtv.tv_usec);
2547 otv = tv;
2548 }
2549 else if (tflag > 2) {
2550 tprintf("%ld.%06ld ",
2551 (long) tv.tv_sec, (long) tv.tv_usec);
2552 }
2553 else {
2554 time_t local = tv.tv_sec;
2555 strftime(str, sizeof(str), "%T", localtime(&local));
2556 if (tflag > 1)
2557 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2558 else
2559 tprintf("%s ", str);
2560 }
2561 }
2562 if (iflag)
2563 printcall(tcp);
2564}
2565
2566void
2567tabto(col)
2568int col;
2569{
2570 if (curcol < col)
2571 tprintf("%*s", col - curcol, "");
2572}
2573
2574void
2575printtrailer(tcp)
2576struct tcb *tcp;
2577{
2578 tprintf("\n");
2579 tcp_last = NULL;
2580}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002581
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002582#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002583
2584int mp_ioctl (int fd, int cmd, void *arg, int size) {
2585
2586 struct iovec iov[2];
2587 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002588
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002589 iov[0].iov_base = &cmd;
2590 iov[0].iov_len = sizeof cmd;
2591 if (arg) {
2592 ++n;
2593 iov[1].iov_base = arg;
2594 iov[1].iov_len = size;
2595 }
Roland McGrath553a6092002-12-16 20:40:39 +00002596
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002597 return writev (fd, iov, n);
2598}
2599
2600#endif