blob: 341ed04adeb10b9ccb58084773318ecfdfba9e51 [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
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000619main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000620{
621 extern int optind;
622 extern char *optarg;
623 struct tcb *tcp;
624 int c, pid = 0;
625 struct sigaction sa;
626
627 static char buf[BUFSIZ];
628
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000629 progname = argv[0] ? argv[0] : "strace";
630
Roland McGrathee9d4352002-12-18 04:16:10 +0000631 /* Allocate the initial tcbtab. */
632 tcbtabsize = argc; /* Surely enough for all -p args. */
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000633 if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) {
634 fprintf(stderr, "%s: out of memory\n", progname);
635 exit(1);
636 }
637 if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
638 fprintf(stderr, "%s: out of memory\n", progname);
639 exit(1);
640 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000641 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
642 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
643
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000644 outf = stderr;
645 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000646 set_sortby(DEFAULT_SORTBY);
647 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648 qualify("trace=all");
649 qualify("abbrev=all");
650 qualify("verbose=all");
651 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000653 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000654 switch (c) {
655 case 'c':
656 cflag++;
657 dtime++;
658 break;
659 case 'd':
660 debug++;
661 break;
662 case 'f':
663 followfork++;
664 break;
665 case 'F':
666 followvfork++;
667 break;
668 case 'h':
669 usage(stdout, 0);
670 break;
671 case 'i':
672 iflag++;
673 break;
674 case 'q':
675 qflag++;
676 break;
677 case 'r':
678 rflag++;
679 tflag++;
680 break;
681 case 't':
682 tflag++;
683 break;
684 case 'T':
685 dtime++;
686 break;
687 case 'x':
688 xflag++;
689 break;
690 case 'v':
691 qualify("abbrev=none");
692 break;
693 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000694 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 exit(0);
696 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000697 case 'z':
698 not_failing_only = 1;
699 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700 case 'a':
701 acolumn = atoi(optarg);
702 break;
703 case 'e':
704 qualify(optarg);
705 break;
706 case 'o':
707 outfname = strdup(optarg);
708 break;
709 case 'O':
710 set_overhead(atoi(optarg));
711 break;
712 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000713 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 fprintf(stderr, "%s: Invalid process id: %s\n",
715 progname, optarg);
716 break;
717 }
718 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000719 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720 break;
721 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000722 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000723 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000724 progname);
725 exit(1);
726 }
727 tcp->flags |= TCB_ATTACHED;
728 pflag_seen++;
729 break;
730 case 's':
731 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000732 if (max_strlen < 0) {
733 fprintf(stderr,
734 "%s: invalid -s argument: %s\n",
735 progname, optarg);
736 exit(1);
737 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000738 break;
739 case 'S':
740 set_sortby(optarg);
741 break;
742 case 'u':
743 username = strdup(optarg);
744 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000745 case 'E':
746 if (putenv(optarg) < 0) {
747 fprintf(stderr, "%s: out of memory\n",
748 progname);
749 exit(1);
750 }
751 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752 default:
753 usage(stderr, 1);
754 break;
755 }
756 }
757
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000758 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000759 usage(stderr, 1);
760
Roland McGrathcb9def62006-04-25 07:48:03 +0000761 if (followfork > 1 && cflag) {
762 fprintf(stderr,
763 "%s: -c and -ff are mutually exclusive options\n",
764 progname);
765 exit(1);
766 }
767
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000768 /* See if they want to run as another user. */
769 if (username != NULL) {
770 struct passwd *pent;
771
772 if (getuid() != 0 || geteuid() != 0) {
773 fprintf(stderr,
774 "%s: you must be root to use the -u option\n",
775 progname);
776 exit(1);
777 }
778 if ((pent = getpwnam(username)) == NULL) {
779 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000780 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 exit(1);
782 }
783 run_uid = pent->pw_uid;
784 run_gid = pent->pw_gid;
785 }
786 else {
787 run_uid = getuid();
788 run_gid = getgid();
789 }
790
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 /* Check if they want to redirect the output. */
792 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000793 /* See if they want to pipe the output. */
794 if (outfname[0] == '|' || outfname[0] == '!') {
795 /*
796 * We can't do the <outfname>.PID funny business
797 * when using popen, so prohibit it.
798 */
799 if (followfork > 1) {
800 fprintf(stderr, "\
801%s: piping the output and -ff are mutually exclusive options\n",
802 progname);
803 exit(1);
804 }
805
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000806 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000807 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000808 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000809 else if (followfork <= 1 &&
810 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 }
813
Roland McGrath37b9a662003-11-07 02:26:54 +0000814 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000816 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000817 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000818 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000819 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000820 /* Valid states here:
821 optind < argc pflag_seen outfname interactive
822 1 0 0 1
823 0 1 0 1
824 1 0 1 0
825 0 1 1 1
826 */
827
828 /* STARTUP_CHILD must be called before the signal handlers get
829 installed below as they are inherited into the spawned process.
830 Also we do not need to be protected by them as during interruption
831 in the STARTUP_CHILD mode we kill the spawned process anyway. */
832 if (!pflag_seen)
833 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000835 sigemptyset(&empty_set);
836 sigemptyset(&blocked_set);
837 sa.sa_handler = SIG_IGN;
838 sigemptyset(&sa.sa_mask);
839 sa.sa_flags = 0;
840 sigaction(SIGTTOU, &sa, NULL);
841 sigaction(SIGTTIN, &sa, NULL);
842 if (interactive) {
843 sigaddset(&blocked_set, SIGHUP);
844 sigaddset(&blocked_set, SIGINT);
845 sigaddset(&blocked_set, SIGQUIT);
846 sigaddset(&blocked_set, SIGPIPE);
847 sigaddset(&blocked_set, SIGTERM);
848 sa.sa_handler = interrupt;
849#ifdef SUNOS4
850 /* POSIX signals on sunos4.1 are a little broken. */
851 sa.sa_flags = SA_INTERRUPT;
852#endif /* SUNOS4 */
853 }
854 sigaction(SIGHUP, &sa, NULL);
855 sigaction(SIGINT, &sa, NULL);
856 sigaction(SIGQUIT, &sa, NULL);
857 sigaction(SIGPIPE, &sa, NULL);
858 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000859#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000860 sa.sa_handler = reaper;
861 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000862#else
863 /* Make sure SIGCHLD has the default action so that waitpid
864 definitely works without losing track of children. The user
865 should not have given us a bogus state to inherit, but he might
866 have. Arguably we should detect SIG_IGN here and pass it on
867 to children, but probably noone really needs that. */
868 sa.sa_handler = SIG_DFL;
869 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000870#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871
Roland McGrath02203312007-06-11 22:06:31 +0000872 if (pflag_seen)
873 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000874
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000875 if (trace() < 0)
876 exit(1);
877 cleanup();
878 exit(0);
879}
880
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000881int
882expand_tcbtab()
883{
884 /* Allocate some more TCBs and expand the table.
885 We don't want to relocate the TCBs because our
886 callers have pointers and it would be a pain.
887 So tcbtab is a table of pointers. Since we never
888 free the TCBs, we allocate a single chunk of many. */
889 struct tcb **newtab = (struct tcb **)
890 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
891 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
892 sizeof *newtcbs);
893 int i;
894 if (newtab == NULL || newtcbs == NULL) {
895 if (newtab != NULL)
896 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000897 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
898 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000899 return 1;
900 }
901 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
902 newtab[i] = &newtcbs[i - tcbtabsize];
903 tcbtabsize *= 2;
904 tcbtab = newtab;
905
906 return 0;
907}
908
909
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000911alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912{
913 int i;
914 struct tcb *tcp;
915
Roland McGrathee9d4352002-12-18 04:16:10 +0000916 for (i = 0; i < tcbtabsize; i++) {
917 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000918 if ((tcp->flags & TCB_INUSE) == 0) {
919 tcp->pid = pid;
920 tcp->parent = NULL;
921 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000922 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000923#ifdef TCB_CLONE_THREAD
924 tcp->nclone_threads = tcp->nclone_detached = 0;
925 tcp->nclone_waiting = 0;
926#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 tcp->flags = TCB_INUSE | TCB_STARTUP;
928 tcp->outf = outf; /* Initialise to current out file */
929 tcp->stime.tv_sec = 0;
930 tcp->stime.tv_usec = 0;
931 tcp->pfd = -1;
932 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000933 if (command_options_parsed)
934 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935 return tcp;
936 }
937 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000938 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 return NULL;
940}
941
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000942#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000943int
944proc_open(tcp, attaching)
945struct tcb *tcp;
946int attaching;
947{
948 char proc[32];
949 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000950#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000951 int i;
952 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 sigset_t signals;
954 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000955#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956#ifndef HAVE_POLLABLE_PROCFS
957 static int last_pfd;
958#endif
959
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000960#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000961 /* Open the process pseudo-files in /proc. */
962 sprintf(proc, "/proc/%d/ctl", tcp->pid);
963 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964 perror("strace: open(\"/proc/...\", ...)");
965 return -1;
966 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000967 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 return -1;
969 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000970 sprintf(proc, "/proc/%d/status", tcp->pid);
971 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
972 perror("strace: open(\"/proc/...\", ...)");
973 return -1;
974 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000975 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000976 return -1;
977 }
978 sprintf(proc, "/proc/%d/as", tcp->pid);
979 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
980 perror("strace: open(\"/proc/...\", ...)");
981 return -1;
982 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000983 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000984 return -1;
985 }
986#else
987 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000988#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000989 sprintf(proc, "/proc/%d", tcp->pid);
990 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000991#else /* FREEBSD */
992 sprintf(proc, "/proc/%d/mem", tcp->pid);
993 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
994#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000995 perror("strace: open(\"/proc/...\", ...)");
996 return -1;
997 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000998 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000999 return -1;
1000 }
1001#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001002#ifdef FREEBSD
1003 sprintf(proc, "/proc/%d/regs", tcp->pid);
1004 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1005 perror("strace: open(\"/proc/.../regs\", ...)");
1006 return -1;
1007 }
1008 if (cflag) {
1009 sprintf(proc, "/proc/%d/status", tcp->pid);
1010 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1011 perror("strace: open(\"/proc/.../status\", ...)");
1012 return -1;
1013 }
1014 } else
1015 tcp->pfd_status = -1;
1016#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001017 rebuild_pollv();
1018 if (!attaching) {
1019 /*
1020 * Wait for the child to pause. Because of a race
1021 * condition we have to poll for the event.
1022 */
1023 for (;;) {
1024 if (IOCTL_STATUS (tcp) < 0) {
1025 perror("strace: PIOCSTATUS");
1026 return -1;
1027 }
1028 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001029 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001030 }
1031 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001032#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001033 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001034 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001035 perror("strace: PIOCSTOP");
1036 return -1;
1037 }
Roland McGrath553a6092002-12-16 20:40:39 +00001038#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039#ifdef PIOCSET
1040 /* Set Run-on-Last-Close. */
1041 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001042 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 perror("PIOCSET PR_RLC");
1044 return -1;
1045 }
1046 /* Set or Reset Inherit-on-Fork. */
1047 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001048 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 perror("PIOC{SET,RESET} PR_FORK");
1050 return -1;
1051 }
1052#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001053#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1055 perror("PIOCSRLC");
1056 return -1;
1057 }
1058 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1059 perror("PIOC{S,R}FORK");
1060 return -1;
1061 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001062#else /* FREEBSD */
1063 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1064 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1065 perror("PIOCGFL");
1066 return -1;
1067 }
1068 arg &= ~PF_LINGER;
1069 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1070 perror("PIOCSFL");
1071 return -1;
1072 }
1073#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001075#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001076 /* Enable all syscall entries we care about. */
1077 premptyset(&syscalls);
1078 for (i = 1; i < MAX_QUALS; ++i) {
1079 if (i > (sizeof syscalls) * CHAR_BIT) break;
1080 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1081 }
1082 praddset (&syscalls, SYS_execve);
1083 if (followfork) {
1084 praddset (&syscalls, SYS_fork);
1085#ifdef SYS_forkall
1086 praddset (&syscalls, SYS_forkall);
1087#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001088#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001089 praddset (&syscalls, SYS_fork1);
1090#endif
1091#ifdef SYS_rfork1
1092 praddset (&syscalls, SYS_rfork1);
1093#endif
1094#ifdef SYS_rforkall
1095 praddset (&syscalls, SYS_rforkall);
1096#endif
1097 }
1098 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 perror("PIOCSENTRY");
1100 return -1;
1101 }
John Hughes19e49982001-10-19 08:59:12 +00001102 /* Enable the syscall exits. */
1103 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 perror("PIOSEXIT");
1105 return -1;
1106 }
John Hughes19e49982001-10-19 08:59:12 +00001107 /* Enable signals we care about. */
1108 premptyset(&signals);
1109 for (i = 1; i < MAX_QUALS; ++i) {
1110 if (i > (sizeof signals) * CHAR_BIT) break;
1111 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1112 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001113 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001114 perror("PIOCSTRACE");
1115 return -1;
1116 }
John Hughes19e49982001-10-19 08:59:12 +00001117 /* Enable faults we care about */
1118 premptyset(&faults);
1119 for (i = 1; i < MAX_QUALS; ++i) {
1120 if (i > (sizeof faults) * CHAR_BIT) break;
1121 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1122 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001123 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 perror("PIOCSFAULT");
1125 return -1;
1126 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001127#else /* FREEBSD */
1128 /* set events flags. */
1129 arg = S_SIG | S_SCE | S_SCX ;
1130 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1131 perror("PIOCBIS");
1132 return -1;
1133 }
1134#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 if (!attaching) {
1136#ifdef MIPS
1137 /*
1138 * The SGI PRSABORT doesn't work for pause() so
1139 * we send it a caught signal to wake it up.
1140 */
1141 kill(tcp->pid, SIGINT);
1142#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001143#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001145 arg = PRSABORT;
1146 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 perror("PIOCRUN");
1148 return -1;
1149 }
Roland McGrath553a6092002-12-16 20:40:39 +00001150#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001151#endif /* !MIPS*/
1152#ifdef FREEBSD
1153 /* wake up the child if it received the SIGSTOP */
1154 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001155#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 for (;;) {
1157 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001158 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 perror("PIOCWSTOP");
1160 return -1;
1161 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001162 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001163 tcp->flags &= ~TCB_INSYSCALL;
1164 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001165 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 break;
1167 }
1168 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001169#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001170 arg = 0;
1171 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001172#else /* FREEBSD */
1173 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001174#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 perror("PIOCRUN");
1176 return -1;
1177 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001178#ifdef FREEBSD
1179 /* handle the case where we "opened" the child before
1180 it did the kill -STOP */
1181 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1182 tcp->status.PR_WHAT == SIGSTOP)
1183 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001184#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001186#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001188#else /* FREEBSD */
1189 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001190 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001191 /* We are attaching to an already running process.
1192 * Try to figure out the state of the process in syscalls,
1193 * to handle the first event well.
1194 * This is done by having a look at the "wchan" property of the
1195 * process, which tells where it is stopped (if it is). */
1196 FILE * status;
1197 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001198
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001199 sprintf(proc, "/proc/%d/status", tcp->pid);
1200 status = fopen(proc, "r");
1201 if (status &&
1202 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1203 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1204 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1205 strcmp(wchan, "stopevent")) {
1206 /* The process is asleep in the middle of a syscall.
1207 Fake the syscall entry event */
1208 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1209 tcp->status.PR_WHY = PR_SYSENTRY;
1210 trace_syscall(tcp);
1211 }
1212 if (status)
1213 fclose(status);
1214 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001215 }
1216#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217#ifndef HAVE_POLLABLE_PROCFS
1218 if (proc_poll_pipe[0] != -1)
1219 proc_poller(tcp->pfd);
1220 else if (nprocs > 1) {
1221 proc_poll_open();
1222 proc_poller(last_pfd);
1223 proc_poller(tcp->pfd);
1224 }
1225 last_pfd = tcp->pfd;
1226#endif /* !HAVE_POLLABLE_PROCFS */
1227 return 0;
1228}
1229
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001230#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001232struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233pid2tcb(pid)
1234int pid;
1235{
1236 int i;
1237 struct tcb *tcp;
1238
Roland McGrathee9d4352002-12-18 04:16:10 +00001239 for (i = 0; i < tcbtabsize; i++) {
1240 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 if (pid && tcp->pid != pid)
1242 continue;
1243 if (tcp->flags & TCB_INUSE)
1244 return tcp;
1245 }
1246 return NULL;
1247}
1248
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001249#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250
1251static struct tcb *
1252pfd2tcb(pfd)
1253int pfd;
1254{
1255 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256
Roland McGrathca16be82003-01-10 19:55:28 +00001257 for (i = 0; i < tcbtabsize; i++) {
1258 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001259 if (tcp->pfd != pfd)
1260 continue;
1261 if (tcp->flags & TCB_INUSE)
1262 return tcp;
1263 }
1264 return NULL;
1265}
1266
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001267#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268
1269void
1270droptcb(tcp)
1271struct tcb *tcp;
1272{
1273 if (tcp->pid == 0)
1274 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001275#ifdef TCB_CLONE_THREAD
1276 if (tcp->nclone_threads > 0) {
1277 /* There are other threads left in this process, but this
1278 is the one whose PID represents the whole process.
1279 We need to keep this record around as a zombie until
1280 all the threads die. */
1281 tcp->flags |= TCB_EXITING;
1282 return;
1283 }
1284#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285 nprocs--;
1286 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001287
Roland McGrathe29341c2003-01-10 20:14:20 +00001288 if (tcp->parent != NULL) {
1289 tcp->parent->nchildren--;
1290#ifdef TCB_CLONE_THREAD
1291 if (tcp->flags & TCB_CLONE_DETACHED)
1292 tcp->parent->nclone_detached--;
1293 if (tcp->flags & TCB_CLONE_THREAD)
1294 tcp->parent->nclone_threads--;
1295#endif
Roland McGrath09623452003-05-23 02:27:13 +00001296#ifdef TCB_CLONE_DETACHED
1297 if (!(tcp->flags & TCB_CLONE_DETACHED))
1298#endif
1299 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001300#ifdef LINUX
1301 /* Update `tcp->parent->parent->nchildren' and the other fields
1302 like NCLONE_DETACHED, only for zombie group leader that has
1303 already reported and been short-circuited at the top of this
1304 function. The same condition as at the top of DETACH. */
1305 if ((tcp->flags & TCB_CLONE_THREAD) &&
1306 tcp->parent->nclone_threads == 0 &&
1307 (tcp->parent->flags & TCB_EXITING))
1308 droptcb(tcp->parent);
1309#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001310 tcp->parent = NULL;
1311 }
1312
1313 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 if (tcp->pfd != -1) {
1315 close(tcp->pfd);
1316 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#ifdef FREEBSD
1318 if (tcp->pfd_reg != -1) {
1319 close(tcp->pfd_reg);
1320 tcp->pfd_reg = -1;
1321 }
1322 if (tcp->pfd_status != -1) {
1323 close(tcp->pfd_status);
1324 tcp->pfd_status = -1;
1325 }
Roland McGrath553a6092002-12-16 20:40:39 +00001326#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001327#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001328 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329#endif
1330 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001331
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001332 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001334
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335 tcp->outf = 0;
1336}
1337
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339
1340static int
1341resume(tcp)
1342struct tcb *tcp;
1343{
1344 if (tcp == NULL)
1345 return -1;
1346
1347 if (!(tcp->flags & TCB_SUSPENDED)) {
1348 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1349 return -1;
1350 }
1351 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001352#ifdef TCB_CLONE_THREAD
1353 if (tcp->flags & TCB_CLONE_THREAD)
1354 tcp->parent->nclone_waiting--;
1355#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356
1357 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1358 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1359 return -1;
1360 }
1361
1362 if (!qflag)
1363 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1364 return 0;
1365}
1366
Roland McGrath1bfd3102007-08-03 10:02:00 +00001367static int
1368resume_from_tcp (struct tcb *tcp)
1369{
1370 int error = 0;
1371 int resumed = 0;
1372
1373 /* XXX This won't always be quite right (but it never was).
1374 A waiter with argument 0 or < -1 is waiting for any pid in
1375 a particular pgrp, which this child might or might not be
1376 in. The waiter will only wake up if it's argument is -1
1377 or if it's waiting for tcp->pid's pgrp. It makes a
1378 difference to wake up a waiter when there might be more
1379 traced children, because it could get a false ECHILD
1380 error. OTOH, if this was the last child in the pgrp, then
1381 it ought to wake up and get ECHILD. We would have to
1382 search the system for all pid's in the pgrp to be sure.
1383
1384 && (t->waitpid == -1 ||
1385 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1386 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1387 */
1388
1389 if (tcp->parent &&
1390 (tcp->parent->flags & TCB_SUSPENDED) &&
1391 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1392 error = resume(tcp->parent);
1393 ++resumed;
1394 }
1395#ifdef TCB_CLONE_THREAD
1396 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1397 /* Some other threads of our parent are waiting too. */
1398 unsigned int i;
1399
1400 /* Resume all the threads that were waiting for this PID. */
1401 for (i = 0; i < tcbtabsize; i++) {
1402 struct tcb *t = tcbtab[i];
1403 if (t->parent == tcp->parent && t != tcp
1404 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1405 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1406 && t->waitpid == tcp->pid) {
1407 error |= resume (t);
1408 ++resumed;
1409 }
1410 }
1411 if (resumed == 0)
1412 /* Noone was waiting for this PID in particular,
1413 so now we might need to resume some wildcarders. */
1414 for (i = 0; i < tcbtabsize; i++) {
1415 struct tcb *t = tcbtab[i];
1416 if (t->parent == tcp->parent && t != tcp
1417 && ((t->flags
1418 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1419 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1420 && t->waitpid <= 0
1421 ) {
1422 error |= resume (t);
1423 break;
1424 }
1425 }
1426 }
1427
1428 return error;
1429}
1430#endif
1431
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001432#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433
Roland McGrath0a463882007-07-05 18:43:16 +00001434/* detach traced process; continue with sig
1435 Never call DETACH twice on the same process as both unattached and
1436 attached-unstopped processes give the same ESRCH. For unattached process we
1437 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438
1439static int
1440detach(tcp, sig)
1441struct tcb *tcp;
1442int sig;
1443{
1444 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001445#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001446 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001447 struct tcb *zombie = NULL;
1448
1449 /* If the group leader is lingering only because of this other
1450 thread now dying, then detach the leader as well. */
1451 if ((tcp->flags & TCB_CLONE_THREAD) &&
1452 tcp->parent->nclone_threads == 1 &&
1453 (tcp->parent->flags & TCB_EXITING))
1454 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001455#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456
1457 if (tcp->flags & TCB_BPTSET)
1458 sig = SIGKILL;
1459
1460#ifdef LINUX
1461 /*
1462 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001463 * before detaching. Arghh. We go through hoops
1464 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001465 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001466#if defined(SPARC)
1467#undef PTRACE_DETACH
1468#define PTRACE_DETACH PTRACE_SUNDETACH
1469#endif
Roland McGrath02203312007-06-11 22:06:31 +00001470 /*
1471 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1472 * expected SIGSTOP. We must catch exactly one as otherwise the
1473 * detached process would be left stopped (process state T).
1474 */
1475 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1477 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001478 }
1479 else if (errno != ESRCH) {
1480 /* Shouldn't happen. */
1481 perror("detach: ptrace(PTRACE_DETACH, ...)");
1482 }
Roland McGrath134813a2007-06-02 00:07:33 +00001483 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1484 : tcp->pid),
1485 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001486 if (errno != ESRCH)
1487 perror("detach: checking sanity");
1488 }
Roland McGrath02203312007-06-11 22:06:31 +00001489 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1490 ? tcp->parent->pid : tcp->pid),
1491 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001492 if (errno != ESRCH)
1493 perror("detach: stopping child");
1494 }
Roland McGrath02203312007-06-11 22:06:31 +00001495 else
1496 catch_sigstop = 1;
1497 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001499#ifdef __WALL
1500 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1501 if (errno == ECHILD) /* Already gone. */
1502 break;
1503 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001504 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001505 break;
1506 }
1507#endif /* __WALL */
1508 /* No __WALL here. */
1509 if (waitpid(tcp->pid, &status, 0) < 0) {
1510 if (errno != ECHILD) {
1511 perror("detach: waiting");
1512 break;
1513 }
1514#ifdef __WCLONE
1515 /* If no processes, try clones. */
1516 if (wait4(tcp->pid, &status, __WCLONE,
1517 NULL) < 0) {
1518 if (errno != ECHILD)
1519 perror("detach: waiting");
1520 break;
1521 }
1522#endif /* __WCLONE */
1523 }
1524#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001525 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001526#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 if (!WIFSTOPPED(status)) {
1528 /* Au revoir, mon ami. */
1529 break;
1530 }
1531 if (WSTOPSIG(status) == SIGSTOP) {
1532 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001533 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 if (errno != ESRCH)
1535 perror("detach: ptrace(PTRACE_DETACH, ...)");
1536 /* I died trying. */
1537 }
1538 break;
1539 }
1540 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001541 WSTOPSIG(status) == SIGTRAP ?
1542 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543 if (errno != ESRCH)
1544 perror("detach: ptrace(PTRACE_CONT, ...)");
1545 break;
1546 }
1547 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001548#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549
1550#if defined(SUNOS4)
1551 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1552 if (sig && kill(tcp->pid, sig) < 0)
1553 perror("detach: kill");
1554 sig = 0;
1555 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1556 perror("detach: ptrace(PTRACE_DETACH, ...)");
1557#endif /* SUNOS4 */
1558
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001559#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001560 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001561#endif
1562
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 if (!qflag)
1564 fprintf(stderr, "Process %u detached\n", tcp->pid);
1565
1566 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001567
1568#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001569 if (zombie != NULL) {
1570 /* TCP no longer exists therefore you must not detach () it. */
1571 droptcb(zombie);
1572 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001573#endif
1574
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575 return error;
1576}
1577
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001578#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579
1580static void
1581reaper(sig)
1582int sig;
1583{
1584 int pid;
1585 int status;
1586
1587 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1588#if 0
1589 struct tcb *tcp;
1590
1591 tcp = pid2tcb(pid);
1592 if (tcp)
1593 droptcb(tcp);
1594#endif
1595 }
1596}
1597
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001598#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599
1600static void
1601cleanup()
1602{
1603 int i;
1604 struct tcb *tcp;
1605
Roland McGrathee9d4352002-12-18 04:16:10 +00001606 for (i = 0; i < tcbtabsize; i++) {
1607 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 if (!(tcp->flags & TCB_INUSE))
1609 continue;
1610 if (debug)
1611 fprintf(stderr,
1612 "cleanup: looking at pid %u\n", tcp->pid);
1613 if (tcp_last &&
1614 (!outfname || followfork < 2 || tcp_last == tcp)) {
1615 tprintf(" <unfinished ...>\n");
1616 tcp_last = NULL;
1617 }
1618 if (tcp->flags & TCB_ATTACHED)
1619 detach(tcp, 0);
1620 else {
1621 kill(tcp->pid, SIGCONT);
1622 kill(tcp->pid, SIGTERM);
1623 }
1624 }
1625 if (cflag)
1626 call_summary(outf);
1627}
1628
1629static void
1630interrupt(sig)
1631int sig;
1632{
1633 interrupted = 1;
1634}
1635
1636#ifndef HAVE_STRERROR
1637
Roland McGrath6d2b3492002-12-30 00:51:30 +00001638#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639extern int sys_nerr;
1640extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001641#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642
1643const char *
1644strerror(errno)
1645int errno;
1646{
1647 static char buf[64];
1648
1649 if (errno < 1 || errno >= sys_nerr) {
1650 sprintf(buf, "Unknown error %d", errno);
1651 return buf;
1652 }
1653 return sys_errlist[errno];
1654}
1655
1656#endif /* HAVE_STERRROR */
1657
1658#ifndef HAVE_STRSIGNAL
1659
Roland McGrath8f474e02003-01-14 07:53:33 +00001660#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001661extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001663#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1664extern char *_sys_siglist[];
1665#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666
1667const char *
1668strsignal(sig)
1669int sig;
1670{
1671 static char buf[64];
1672
1673 if (sig < 1 || sig >= NSIG) {
1674 sprintf(buf, "Unknown signal %d", sig);
1675 return buf;
1676 }
1677#ifdef HAVE__SYS_SIGLIST
1678 return _sys_siglist[sig];
1679#else
1680 return sys_siglist[sig];
1681#endif
1682}
1683
1684#endif /* HAVE_STRSIGNAL */
1685
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001686#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687
1688static void
1689rebuild_pollv()
1690{
1691 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692
Roland McGrathee9d4352002-12-18 04:16:10 +00001693 if (pollv != NULL)
1694 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001695 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001696 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001697 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001698 exit(1);
1699 }
1700
Roland McGrathca16be82003-01-10 19:55:28 +00001701 for (i = j = 0; i < tcbtabsize; i++) {
1702 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 if (!(tcp->flags & TCB_INUSE))
1704 continue;
1705 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001706 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707 j++;
1708 }
1709 if (j != nprocs) {
1710 fprintf(stderr, "strace: proc miscount\n");
1711 exit(1);
1712 }
1713}
1714
1715#ifndef HAVE_POLLABLE_PROCFS
1716
1717static void
1718proc_poll_open()
1719{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720 int i;
1721
1722 if (pipe(proc_poll_pipe) < 0) {
1723 perror("pipe");
1724 exit(1);
1725 }
1726 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001727 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728 exit(1);
1729 }
1730 }
1731}
1732
1733static int
1734proc_poll(pollv, nfds, timeout)
1735struct pollfd *pollv;
1736int nfds;
1737int timeout;
1738{
1739 int i;
1740 int n;
1741 struct proc_pollfd pollinfo;
1742
1743 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1744 return n;
1745 if (n != sizeof(struct proc_pollfd)) {
1746 fprintf(stderr, "panic: short read: %d\n", n);
1747 exit(1);
1748 }
1749 for (i = 0; i < nprocs; i++) {
1750 if (pollv[i].fd == pollinfo.fd)
1751 pollv[i].revents = pollinfo.revents;
1752 else
1753 pollv[i].revents = 0;
1754 }
1755 poller_pid = pollinfo.pid;
1756 return 1;
1757}
1758
1759static void
1760wakeup_handler(sig)
1761int sig;
1762{
1763}
1764
1765static void
1766proc_poller(pfd)
1767int pfd;
1768{
1769 struct proc_pollfd pollinfo;
1770 struct sigaction sa;
1771 sigset_t blocked_set, empty_set;
1772 int i;
1773 int n;
1774 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001775#ifdef FREEBSD
1776 struct procfs_status pfs;
1777#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778
1779 switch (fork()) {
1780 case -1:
1781 perror("fork");
1782 _exit(0);
1783 case 0:
1784 break;
1785 default:
1786 return;
1787 }
1788
1789 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1790 sa.sa_flags = 0;
1791 sigemptyset(&sa.sa_mask);
1792 sigaction(SIGHUP, &sa, NULL);
1793 sigaction(SIGINT, &sa, NULL);
1794 sigaction(SIGQUIT, &sa, NULL);
1795 sigaction(SIGPIPE, &sa, NULL);
1796 sigaction(SIGTERM, &sa, NULL);
1797 sa.sa_handler = wakeup_handler;
1798 sigaction(SIGUSR1, &sa, NULL);
1799 sigemptyset(&blocked_set);
1800 sigaddset(&blocked_set, SIGUSR1);
1801 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1802 sigemptyset(&empty_set);
1803
1804 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1805 perror("getrlimit(RLIMIT_NOFILE, ...)");
1806 _exit(0);
1807 }
1808 n = rl.rlim_cur;
1809 for (i = 0; i < n; i++) {
1810 if (i != pfd && i != proc_poll_pipe[1])
1811 close(i);
1812 }
1813
1814 pollinfo.fd = pfd;
1815 pollinfo.pid = getpid();
1816 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001817#ifndef FREEBSD
1818 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1819#else /* FREEBSD */
1820 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1821#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001822 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823 switch (errno) {
1824 case EINTR:
1825 continue;
1826 case EBADF:
1827 pollinfo.revents = POLLERR;
1828 break;
1829 case ENOENT:
1830 pollinfo.revents = POLLHUP;
1831 break;
1832 default:
1833 perror("proc_poller: PIOCWSTOP");
1834 }
1835 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1836 _exit(0);
1837 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001838 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1840 sigsuspend(&empty_set);
1841 }
1842}
1843
1844#endif /* !HAVE_POLLABLE_PROCFS */
1845
1846static int
1847choose_pfd()
1848{
1849 int i, j;
1850 struct tcb *tcp;
1851
1852 static int last;
1853
1854 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001855 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856 /*
1857 * The previous process is ready to run again. We'll
1858 * let it do so if it is currently in a syscall. This
1859 * heuristic improves the readability of the trace.
1860 */
1861 tcp = pfd2tcb(pollv[last].fd);
1862 if (tcp && (tcp->flags & TCB_INSYSCALL))
1863 return pollv[last].fd;
1864 }
1865
1866 for (i = 0; i < nprocs; i++) {
1867 /* Let competing children run round robin. */
1868 j = (i + last + 1) % nprocs;
1869 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1870 tcp = pfd2tcb(pollv[j].fd);
1871 if (!tcp) {
1872 fprintf(stderr, "strace: lost proc\n");
1873 exit(1);
1874 }
1875 droptcb(tcp);
1876 return -1;
1877 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001878 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879 last = j;
1880 return pollv[j].fd;
1881 }
1882 }
1883 fprintf(stderr, "strace: nothing ready\n");
1884 exit(1);
1885}
1886
1887static int
1888trace()
1889{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001890#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001891 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001892#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893 struct tcb *tcp;
1894 int pfd;
1895 int what;
1896 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001897 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898
1899 for (;;) {
1900 if (interactive)
1901 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1902
1903 if (nprocs == 0)
1904 break;
1905
1906 switch (nprocs) {
1907 case 1:
1908#ifndef HAVE_POLLABLE_PROCFS
1909 if (proc_poll_pipe[0] == -1) {
1910#endif
1911 tcp = pid2tcb(0);
1912 if (!tcp)
1913 continue;
1914 pfd = tcp->pfd;
1915 if (pfd == -1)
1916 continue;
1917 break;
1918#ifndef HAVE_POLLABLE_PROCFS
1919 }
1920 /* fall through ... */
1921#endif /* !HAVE_POLLABLE_PROCFS */
1922 default:
1923#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001924#ifdef POLL_HACK
1925 /* On some systems (e.g. UnixWare) we get too much ugly
1926 "unfinished..." stuff when multiple proceses are in
1927 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001928
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001929 if (in_syscall) {
1930 struct pollfd pv;
1931 tcp = in_syscall;
1932 in_syscall = NULL;
1933 pv.fd = tcp->pfd;
1934 pv.events = POLLWANT;
1935 if ((what = poll (&pv, 1, 1)) < 0) {
1936 if (interrupted)
1937 return 0;
1938 continue;
1939 }
1940 else if (what == 1 && pv.revents & POLLWANT) {
1941 goto FOUND;
1942 }
1943 }
1944#endif
1945
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946 if (poll(pollv, nprocs, INFTIM) < 0) {
1947 if (interrupted)
1948 return 0;
1949 continue;
1950 }
1951#else /* !HAVE_POLLABLE_PROCFS */
1952 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1953 if (interrupted)
1954 return 0;
1955 continue;
1956 }
1957#endif /* !HAVE_POLLABLE_PROCFS */
1958 pfd = choose_pfd();
1959 if (pfd == -1)
1960 continue;
1961 break;
1962 }
1963
1964 /* Look up `pfd' in our table. */
1965 if ((tcp = pfd2tcb(pfd)) == NULL) {
1966 fprintf(stderr, "unknown pfd: %u\n", pfd);
1967 exit(1);
1968 }
John Hughesb6643082002-05-23 11:02:22 +00001969#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001970 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001971#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001972 /* Get the status of the process. */
1973 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001974#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001975 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001976#else /* FREEBSD */
1977 /* Thanks to some scheduling mystery, the first poller
1978 sometimes waits for the already processed end of fork
1979 event. Doing a non blocking poll here solves the problem. */
1980 if (proc_poll_pipe[0] != -1)
1981 ioctl_result = IOCTL_STATUS (tcp);
1982 else
1983 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001984#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985 ioctl_errno = errno;
1986#ifndef HAVE_POLLABLE_PROCFS
1987 if (proc_poll_pipe[0] != -1) {
1988 if (ioctl_result < 0)
1989 kill(poller_pid, SIGKILL);
1990 else
1991 kill(poller_pid, SIGUSR1);
1992 }
1993#endif /* !HAVE_POLLABLE_PROCFS */
1994 }
1995 if (interrupted)
1996 return 0;
1997
1998 if (interactive)
1999 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2000
2001 if (ioctl_result < 0) {
2002 /* Find out what happened if it failed. */
2003 switch (ioctl_errno) {
2004 case EINTR:
2005 case EBADF:
2006 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002007#ifdef FREEBSD
2008 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002009#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010 case ENOENT:
2011 droptcb(tcp);
2012 continue;
2013 default:
2014 perror("PIOCWSTOP");
2015 exit(1);
2016 }
2017 }
2018
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002019#ifdef FREEBSD
2020 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2021 /* discard first event for a syscall we never entered */
2022 IOCTL (tcp->pfd, PIOCRUN, 0);
2023 continue;
2024 }
Roland McGrath553a6092002-12-16 20:40:39 +00002025#endif
2026
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002027 /* clear the just started flag */
2028 tcp->flags &= ~TCB_STARTUP;
2029
2030 /* set current output file */
2031 outf = tcp->outf;
2032
2033 if (cflag) {
2034 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002035#ifdef FREEBSD
2036 char buf[1024];
2037 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002039 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2040 buf[len] = '\0';
2041 sscanf(buf,
2042 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2043 &stime.tv_sec, &stime.tv_usec);
2044 } else
2045 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002046#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2048 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002049#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2051 tcp->stime = stime;
2052 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002053 what = tcp->status.PR_WHAT;
2054 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002055#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2058 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 if (trace_syscall(tcp) < 0) {
2060 fprintf(stderr, "syscall trouble\n");
2061 exit(1);
2062 }
2063 }
2064 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002065#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002066 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002067#ifdef POLL_HACK
2068 in_syscall = tcp;
2069#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 case PR_SYSEXIT:
2071 if (trace_syscall(tcp) < 0) {
2072 fprintf(stderr, "syscall trouble\n");
2073 exit(1);
2074 }
2075 break;
2076 case PR_SIGNALLED:
2077 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2078 printleader(tcp);
2079 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002080 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002082#ifdef PR_INFO
2083 if (tcp->status.PR_INFO.si_signo == what) {
2084 printleader(tcp);
2085 tprintf(" siginfo=");
2086 printsiginfo(&tcp->status.PR_INFO, 1);
2087 printtrailer(tcp);
2088 }
2089#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 }
2091 break;
2092 case PR_FAULTED:
2093 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2094 printleader(tcp);
2095 tprintf("=== FAULT %d ===", what);
2096 printtrailer(tcp);
2097 }
2098 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002099#ifdef FREEBSD
2100 case 0: /* handle case we polled for nothing */
2101 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002102#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002103 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002104 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002105 exit(1);
2106 break;
2107 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002108 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002109#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002110 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002111#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002112 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002113#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 perror("PIOCRUN");
2115 exit(1);
2116 }
2117 }
2118 return 0;
2119}
2120
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002121#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002122
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002123#ifdef TCB_GROUP_EXITING
2124/* Handle an exit detach or death signal that is taking all the
2125 related clone threads with it. This is called in three circumstances:
2126 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2127 SIG == 0 Continuing TCP will perform an exit_group syscall.
2128 SIG == other Continuing TCP with SIG will kill the process.
2129*/
2130static int
2131handle_group_exit(struct tcb *tcp, int sig)
2132{
2133 /* We need to locate our records of all the clone threads
2134 related to TCP, either its children or siblings. */
2135 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2136 ? tcp->parent
2137 : tcp->nclone_detached > 0
2138 ? tcp : NULL);
2139
2140 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002141 if (leader != NULL && leader != tcp &&
2142 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002143 fprintf(stderr,
2144 "PANIC: handle_group_exit: %d leader %d\n",
2145 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002146 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002147#ifndef USE_PROCFS
2148 resume_from_tcp (tcp);
2149#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002150 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002151 }
2152 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002153 /* Mark that we are taking the process down. */
2154 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002155 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002156 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002157 if (leader != NULL && leader != tcp)
2158 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002159 }
2160 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2161 perror("strace: ptrace(PTRACE_CONT, ...)");
2162 cleanup();
2163 return -1;
2164 }
2165 else {
Roland McGrath05690952004-10-20 01:00:27 +00002166 if (leader != NULL)
2167 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002168 if (leader != NULL && leader != tcp)
2169 droptcb(tcp);
2170 /* The leader will report to us as parent now,
2171 and then we'll get to the SIG==-1 case. */
2172 return 0;
2173 }
2174 }
2175
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002176 return 0;
2177}
2178#endif
2179
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002180static int
2181trace()
2182{
2183 int pid;
2184 int wait_errno;
2185 int status;
2186 struct tcb *tcp;
2187#ifdef LINUX
2188 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002189#ifdef __WALL
2190 static int wait4_options = __WALL;
2191#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192#endif /* LINUX */
2193
2194 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002195 if (interrupted)
2196 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 if (interactive)
2198 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2199#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002200#ifdef __WALL
2201 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002202 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002203 /* this kernel does not support __WALL */
2204 wait4_options &= ~__WALL;
2205 errno = 0;
2206 pid = wait4(-1, &status, wait4_options,
2207 cflag ? &ru : NULL);
2208 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002209 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002210 /* most likely a "cloned" process */
2211 pid = wait4(-1, &status, __WCLONE,
2212 cflag ? &ru : NULL);
2213 if (pid == -1) {
2214 fprintf(stderr, "strace: clone wait4 "
2215 "failed: %s\n", strerror(errno));
2216 }
2217 }
2218#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002219 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002220#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221#endif /* LINUX */
2222#ifdef SUNOS4
2223 pid = wait(&status);
2224#endif /* SUNOS4 */
2225 wait_errno = errno;
2226 if (interactive)
2227 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2228
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 if (pid == -1) {
2230 switch (wait_errno) {
2231 case EINTR:
2232 continue;
2233 case ECHILD:
2234 /*
2235 * We would like to verify this case
2236 * but sometimes a race in Solbourne's
2237 * version of SunOS sometimes reports
2238 * ECHILD before sending us SIGCHILD.
2239 */
2240#if 0
2241 if (nprocs == 0)
2242 return 0;
2243 fprintf(stderr, "strace: proc miscount\n");
2244 exit(1);
2245#endif
2246 return 0;
2247 default:
2248 errno = wait_errno;
2249 perror("strace: wait");
2250 return -1;
2251 }
2252 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002253 if (pid == popen_pid) {
2254 if (WIFEXITED(status) || WIFSIGNALED(status))
2255 popen_pid = -1;
2256 continue;
2257 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002258 if (debug)
2259 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2260
2261 /* Look up `pid' in our table. */
2262 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002263#ifdef LINUX
2264 if (followfork || followvfork) {
2265 /* This is needed to go with the CLONE_PTRACE
2266 changes in process.c/util.c: we might see
2267 the child's initial trap before we see the
2268 parent return from the clone syscall.
2269 Leave the child suspended until the parent
2270 returns from its system call. Only then
2271 will we have the association of parent and
2272 child so that we know how to do clearbpt
2273 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002274 if (nprocs == tcbtabsize &&
2275 expand_tcbtab())
2276 tcp = NULL;
2277 else
2278 tcp = alloctcb(pid);
2279 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002280 kill(pid, SIGKILL); /* XXX */
2281 return 0;
2282 }
2283 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002284 if (!qflag)
2285 fprintf(stderr, "\
2286Process %d attached (waiting for parent)\n",
2287 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002288 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002289 else
2290 /* This can happen if a clone call used
2291 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002292#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002293 {
2294 fprintf(stderr, "unknown pid: %u\n", pid);
2295 if (WIFSTOPPED(status))
2296 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2297 exit(1);
2298 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002299 }
2300 /* set current output file */
2301 outf = tcp->outf;
2302 if (cflag) {
2303#ifdef LINUX
2304 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2305 tcp->stime = ru.ru_stime;
2306#endif /* !LINUX */
2307 }
2308
2309 if (tcp->flags & TCB_SUSPENDED) {
2310 /*
2311 * Apparently, doing any ptrace() call on a stopped
2312 * process, provokes the kernel to report the process
2313 * status again on a subsequent wait(), even if the
2314 * process has not been actually restarted.
2315 * Since we have inspected the arguments of suspended
2316 * processes we end up here testing for this case.
2317 */
2318 continue;
2319 }
2320 if (WIFSIGNALED(status)) {
2321 if (!cflag
2322 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2323 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002324 tprintf("+++ killed by %s %s+++",
2325 signame(WTERMSIG(status)),
2326#ifdef WCOREDUMP
2327 WCOREDUMP(status) ? "(core dumped) " :
2328#endif
2329 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 printtrailer(tcp);
2331 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002332#ifdef TCB_GROUP_EXITING
2333 handle_group_exit(tcp, -1);
2334#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002335 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002336#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337 continue;
2338 }
2339 if (WIFEXITED(status)) {
2340 if (debug)
2341 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002342 if ((tcp->flags & TCB_ATTACHED)
2343#ifdef TCB_GROUP_EXITING
2344 && !(tcp->parent && (tcp->parent->flags &
2345 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002346 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002347#endif
2348 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349 fprintf(stderr,
2350 "PANIC: attached pid %u exited\n",
2351 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002352 if (tcp == tcp_last) {
2353 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2354 == TCB_INSYSCALL)
2355 tprintf(" <unfinished ... exit status %d>\n",
2356 WEXITSTATUS(status));
2357 tcp_last = NULL;
2358 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002359#ifdef TCB_GROUP_EXITING
2360 handle_group_exit(tcp, -1);
2361#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002362 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002363#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002364 continue;
2365 }
2366 if (!WIFSTOPPED(status)) {
2367 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2368 droptcb(tcp);
2369 continue;
2370 }
2371 if (debug)
2372 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002373 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374
Roland McGrath02203312007-06-11 22:06:31 +00002375 /*
2376 * Interestingly, the process may stop
2377 * with STOPSIG equal to some other signal
2378 * than SIGSTOP if we happend to attach
2379 * just before the process takes a signal.
2380 */
2381 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002382 /*
2383 * This flag is there to keep us in sync.
2384 * Next time this process stops it should
2385 * really be entering a system call.
2386 */
2387 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002389 /*
2390 * One example is a breakpoint inherited from
2391 * parent through fork ().
2392 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002393 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2394 droptcb(tcp);
2395 cleanup();
2396 return -1;
2397 }
2398 }
2399 goto tracing;
2400 }
2401
2402 if (WSTOPSIG(status) != SIGTRAP) {
2403 if (WSTOPSIG(status) == SIGSTOP &&
2404 (tcp->flags & TCB_SIGTRAPPED)) {
2405 /*
2406 * Trapped attempt to block SIGTRAP
2407 * Hope we are back in control now.
2408 */
2409 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2410 if (ptrace(PTRACE_SYSCALL,
2411 pid, (char *) 1, 0) < 0) {
2412 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2413 cleanup();
2414 return -1;
2415 }
2416 continue;
2417 }
2418 if (!cflag
2419 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002420 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002421#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002422# define PSR_RI 41
2423 struct siginfo si;
2424 unsigned long psr;
2425
2426 upeek(pid, PT_CR_IPSR, &psr);
2427 upeek(pid, PT_CR_IIP, &pc);
2428
2429 pc += (psr >> PSR_RI) & 0x3;
2430 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2431 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002432#elif defined PTRACE_GETSIGINFO
2433 if (WSTOPSIG(status) == SIGSEGV ||
2434 WSTOPSIG(status) == SIGBUS) {
2435 siginfo_t si;
2436 if (ptrace(PTRACE_GETSIGINFO, pid,
2437 0, &si) == 0)
2438 addr = (unsigned long)
2439 si.si_addr;
2440 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002441#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002443 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002444 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002445 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002446 printtrailer(tcp);
2447 }
Roland McGrath05690952004-10-20 01:00:27 +00002448 if (((tcp->flags & TCB_ATTACHED) ||
2449 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002450 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002451#ifdef TCB_GROUP_EXITING
2452 handle_group_exit(tcp, WSTOPSIG(status));
2453#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002455#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456 continue;
2457 }
2458 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2459 WSTOPSIG(status)) < 0) {
2460 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2461 cleanup();
2462 return -1;
2463 }
2464 tcp->flags &= ~TCB_SUSPENDED;
2465 continue;
2466 }
Roland McGrath02203312007-06-11 22:06:31 +00002467 /* we handled the STATUS, we are permitted to interrupt now. */
2468 if (interrupted)
2469 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470 if (trace_syscall(tcp) < 0) {
2471 if (tcp->flags & TCB_ATTACHED)
2472 detach(tcp, 0);
2473 else {
2474 ptrace(PTRACE_KILL,
2475 tcp->pid, (char *) 1, SIGTERM);
2476 droptcb(tcp);
2477 }
2478 continue;
2479 }
2480 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002481#ifdef TCB_GROUP_EXITING
2482 if (tcp->flags & TCB_GROUP_EXITING) {
2483 if (handle_group_exit(tcp, 0) < 0)
2484 return -1;
2485 continue;
2486 }
2487#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488 if (tcp->flags & TCB_ATTACHED)
2489 detach(tcp, 0);
2490 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2491 perror("strace: ptrace(PTRACE_CONT, ...)");
2492 cleanup();
2493 return -1;
2494 }
2495 continue;
2496 }
2497 if (tcp->flags & TCB_SUSPENDED) {
2498 if (!qflag)
2499 fprintf(stderr, "Process %u suspended\n", pid);
2500 continue;
2501 }
2502 tracing:
2503 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2504 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2505 cleanup();
2506 return -1;
2507 }
2508 }
2509 return 0;
2510}
2511
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002512#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513
2514static int curcol;
2515
2516#ifdef __STDC__
2517#include <stdarg.h>
2518#define VA_START(a, b) va_start(a, b)
2519#else
2520#include <varargs.h>
2521#define VA_START(a, b) va_start(a)
2522#endif
2523
2524void
2525#ifdef __STDC__
2526tprintf(const char *fmt, ...)
2527#else
2528tprintf(fmt, va_alist)
2529char *fmt;
2530va_dcl
2531#endif
2532{
2533 va_list args;
2534
2535 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002536 if (outf) {
2537 int n = vfprintf(outf, fmt, args);
2538 if (n < 0 && outf != stderr)
2539 perror(outfname == NULL
2540 ? "<writing to pipe>" : outfname);
2541 else
2542 curcol += n;
2543 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 va_end(args);
2545 return;
2546}
2547
2548void
2549printleader(tcp)
2550struct tcb *tcp;
2551{
2552 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2553 tcp_last->flags |= TCB_REPRINT;
2554 tprintf(" <unfinished ...>\n");
2555 }
2556 curcol = 0;
2557 if ((followfork == 1 || pflag_seen > 1) && outfname)
2558 tprintf("%-5d ", tcp->pid);
2559 else if (nprocs > 1 && !outfname)
2560 tprintf("[pid %5u] ", tcp->pid);
2561 if (tflag) {
2562 char str[sizeof("HH:MM:SS")];
2563 struct timeval tv, dtv;
2564 static struct timeval otv;
2565
2566 gettimeofday(&tv, NULL);
2567 if (rflag) {
2568 if (otv.tv_sec == 0)
2569 otv = tv;
2570 tv_sub(&dtv, &tv, &otv);
2571 tprintf("%6ld.%06ld ",
2572 (long) dtv.tv_sec, (long) dtv.tv_usec);
2573 otv = tv;
2574 }
2575 else if (tflag > 2) {
2576 tprintf("%ld.%06ld ",
2577 (long) tv.tv_sec, (long) tv.tv_usec);
2578 }
2579 else {
2580 time_t local = tv.tv_sec;
2581 strftime(str, sizeof(str), "%T", localtime(&local));
2582 if (tflag > 1)
2583 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2584 else
2585 tprintf("%s ", str);
2586 }
2587 }
2588 if (iflag)
2589 printcall(tcp);
2590}
2591
2592void
2593tabto(col)
2594int col;
2595{
2596 if (curcol < col)
2597 tprintf("%*s", col - curcol, "");
2598}
2599
2600void
2601printtrailer(tcp)
2602struct tcb *tcp;
2603{
2604 tprintf("\n");
2605 tcp_last = NULL;
2606}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002607
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002608#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002609
2610int mp_ioctl (int fd, int cmd, void *arg, int size) {
2611
2612 struct iovec iov[2];
2613 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002614
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002615 iov[0].iov_base = &cmd;
2616 iov[0].iov_len = sizeof cmd;
2617 if (arg) {
2618 ++n;
2619 iov[1].iov_base = arg;
2620 iov[1].iov_len = size;
2621 }
Roland McGrath553a6092002-12-16 20:40:39 +00002622
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002623 return writev (fd, iov, n);
2624}
2625
2626#endif