blob: b71e093b83621ee0e384c4ffbddbf92e3effdfa7 [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 McGrathe29341c2003-01-10 20:14:20 +00001300 tcp->parent = NULL;
1301 }
1302
1303 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 if (tcp->pfd != -1) {
1305 close(tcp->pfd);
1306 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001307#ifdef FREEBSD
1308 if (tcp->pfd_reg != -1) {
1309 close(tcp->pfd_reg);
1310 tcp->pfd_reg = -1;
1311 }
1312 if (tcp->pfd_status != -1) {
1313 close(tcp->pfd_status);
1314 tcp->pfd_status = -1;
1315 }
Roland McGrath553a6092002-12-16 20:40:39 +00001316#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001318 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319#endif
1320 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001321
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001322 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001324
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325 tcp->outf = 0;
1326}
1327
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001328#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329
1330static int
1331resume(tcp)
1332struct tcb *tcp;
1333{
1334 if (tcp == NULL)
1335 return -1;
1336
1337 if (!(tcp->flags & TCB_SUSPENDED)) {
1338 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1339 return -1;
1340 }
1341 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001342#ifdef TCB_CLONE_THREAD
1343 if (tcp->flags & TCB_CLONE_THREAD)
1344 tcp->parent->nclone_waiting--;
1345#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346
1347 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1348 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1349 return -1;
1350 }
1351
1352 if (!qflag)
1353 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1354 return 0;
1355}
1356
Roland McGrath1bfd3102007-08-03 10:02:00 +00001357static int
1358resume_from_tcp (struct tcb *tcp)
1359{
1360 int error = 0;
1361 int resumed = 0;
1362
1363 /* XXX This won't always be quite right (but it never was).
1364 A waiter with argument 0 or < -1 is waiting for any pid in
1365 a particular pgrp, which this child might or might not be
1366 in. The waiter will only wake up if it's argument is -1
1367 or if it's waiting for tcp->pid's pgrp. It makes a
1368 difference to wake up a waiter when there might be more
1369 traced children, because it could get a false ECHILD
1370 error. OTOH, if this was the last child in the pgrp, then
1371 it ought to wake up and get ECHILD. We would have to
1372 search the system for all pid's in the pgrp to be sure.
1373
1374 && (t->waitpid == -1 ||
1375 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1376 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1377 */
1378
1379 if (tcp->parent &&
1380 (tcp->parent->flags & TCB_SUSPENDED) &&
1381 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1382 error = resume(tcp->parent);
1383 ++resumed;
1384 }
1385#ifdef TCB_CLONE_THREAD
1386 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1387 /* Some other threads of our parent are waiting too. */
1388 unsigned int i;
1389
1390 /* Resume all the threads that were waiting for this PID. */
1391 for (i = 0; i < tcbtabsize; i++) {
1392 struct tcb *t = tcbtab[i];
1393 if (t->parent == tcp->parent && t != tcp
1394 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1395 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1396 && t->waitpid == tcp->pid) {
1397 error |= resume (t);
1398 ++resumed;
1399 }
1400 }
1401 if (resumed == 0)
1402 /* Noone was waiting for this PID in particular,
1403 so now we might need to resume some wildcarders. */
1404 for (i = 0; i < tcbtabsize; i++) {
1405 struct tcb *t = tcbtab[i];
1406 if (t->parent == tcp->parent && t != tcp
1407 && ((t->flags
1408 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1409 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1410 && t->waitpid <= 0
1411 ) {
1412 error |= resume (t);
1413 break;
1414 }
1415 }
1416 }
1417
1418 return error;
1419}
1420#endif
1421
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001422#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423
Roland McGrath0a463882007-07-05 18:43:16 +00001424/* detach traced process; continue with sig
1425 Never call DETACH twice on the same process as both unattached and
1426 attached-unstopped processes give the same ESRCH. For unattached process we
1427 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428
1429static int
1430detach(tcp, sig)
1431struct tcb *tcp;
1432int sig;
1433{
1434 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001435#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001436 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001437 struct tcb *zombie = NULL;
1438
1439 /* If the group leader is lingering only because of this other
1440 thread now dying, then detach the leader as well. */
1441 if ((tcp->flags & TCB_CLONE_THREAD) &&
1442 tcp->parent->nclone_threads == 1 &&
1443 (tcp->parent->flags & TCB_EXITING))
1444 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001445#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446
1447 if (tcp->flags & TCB_BPTSET)
1448 sig = SIGKILL;
1449
1450#ifdef LINUX
1451 /*
1452 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001453 * before detaching. Arghh. We go through hoops
1454 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001456#if defined(SPARC)
1457#undef PTRACE_DETACH
1458#define PTRACE_DETACH PTRACE_SUNDETACH
1459#endif
Roland McGrath02203312007-06-11 22:06:31 +00001460 /*
1461 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1462 * expected SIGSTOP. We must catch exactly one as otherwise the
1463 * detached process would be left stopped (process state T).
1464 */
1465 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001466 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1467 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001468 }
1469 else if (errno != ESRCH) {
1470 /* Shouldn't happen. */
1471 perror("detach: ptrace(PTRACE_DETACH, ...)");
1472 }
Roland McGrath134813a2007-06-02 00:07:33 +00001473 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1474 : tcp->pid),
1475 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001476 if (errno != ESRCH)
1477 perror("detach: checking sanity");
1478 }
Roland McGrath02203312007-06-11 22:06:31 +00001479 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1480 ? tcp->parent->pid : tcp->pid),
1481 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001482 if (errno != ESRCH)
1483 perror("detach: stopping child");
1484 }
Roland McGrath02203312007-06-11 22:06:31 +00001485 else
1486 catch_sigstop = 1;
1487 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001489#ifdef __WALL
1490 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1491 if (errno == ECHILD) /* Already gone. */
1492 break;
1493 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001494 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001495 break;
1496 }
1497#endif /* __WALL */
1498 /* No __WALL here. */
1499 if (waitpid(tcp->pid, &status, 0) < 0) {
1500 if (errno != ECHILD) {
1501 perror("detach: waiting");
1502 break;
1503 }
1504#ifdef __WCLONE
1505 /* If no processes, try clones. */
1506 if (wait4(tcp->pid, &status, __WCLONE,
1507 NULL) < 0) {
1508 if (errno != ECHILD)
1509 perror("detach: waiting");
1510 break;
1511 }
1512#endif /* __WCLONE */
1513 }
1514#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001515 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001516#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517 if (!WIFSTOPPED(status)) {
1518 /* Au revoir, mon ami. */
1519 break;
1520 }
1521 if (WSTOPSIG(status) == SIGSTOP) {
1522 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001523 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524 if (errno != ESRCH)
1525 perror("detach: ptrace(PTRACE_DETACH, ...)");
1526 /* I died trying. */
1527 }
1528 break;
1529 }
1530 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001531 WSTOPSIG(status) == SIGTRAP ?
1532 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 if (errno != ESRCH)
1534 perror("detach: ptrace(PTRACE_CONT, ...)");
1535 break;
1536 }
1537 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001538#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539
1540#if defined(SUNOS4)
1541 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1542 if (sig && kill(tcp->pid, sig) < 0)
1543 perror("detach: kill");
1544 sig = 0;
1545 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1546 perror("detach: ptrace(PTRACE_DETACH, ...)");
1547#endif /* SUNOS4 */
1548
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001549#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001550 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001551#endif
1552
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553 if (!qflag)
1554 fprintf(stderr, "Process %u detached\n", tcp->pid);
1555
1556 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001557
1558#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001559 if (zombie != NULL) {
1560 /* TCP no longer exists therefore you must not detach () it. */
1561 droptcb(zombie);
1562 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001563#endif
1564
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565 return error;
1566}
1567
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001568#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569
1570static void
1571reaper(sig)
1572int sig;
1573{
1574 int pid;
1575 int status;
1576
1577 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1578#if 0
1579 struct tcb *tcp;
1580
1581 tcp = pid2tcb(pid);
1582 if (tcp)
1583 droptcb(tcp);
1584#endif
1585 }
1586}
1587
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001588#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589
1590static void
1591cleanup()
1592{
1593 int i;
1594 struct tcb *tcp;
1595
Roland McGrathee9d4352002-12-18 04:16:10 +00001596 for (i = 0; i < tcbtabsize; i++) {
1597 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598 if (!(tcp->flags & TCB_INUSE))
1599 continue;
1600 if (debug)
1601 fprintf(stderr,
1602 "cleanup: looking at pid %u\n", tcp->pid);
1603 if (tcp_last &&
1604 (!outfname || followfork < 2 || tcp_last == tcp)) {
1605 tprintf(" <unfinished ...>\n");
1606 tcp_last = NULL;
1607 }
1608 if (tcp->flags & TCB_ATTACHED)
1609 detach(tcp, 0);
1610 else {
1611 kill(tcp->pid, SIGCONT);
1612 kill(tcp->pid, SIGTERM);
1613 }
1614 }
1615 if (cflag)
1616 call_summary(outf);
1617}
1618
1619static void
1620interrupt(sig)
1621int sig;
1622{
1623 interrupted = 1;
1624}
1625
1626#ifndef HAVE_STRERROR
1627
Roland McGrath6d2b3492002-12-30 00:51:30 +00001628#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629extern int sys_nerr;
1630extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001631#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632
1633const char *
1634strerror(errno)
1635int errno;
1636{
1637 static char buf[64];
1638
1639 if (errno < 1 || errno >= sys_nerr) {
1640 sprintf(buf, "Unknown error %d", errno);
1641 return buf;
1642 }
1643 return sys_errlist[errno];
1644}
1645
1646#endif /* HAVE_STERRROR */
1647
1648#ifndef HAVE_STRSIGNAL
1649
Roland McGrath8f474e02003-01-14 07:53:33 +00001650#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001651extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001653#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1654extern char *_sys_siglist[];
1655#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656
1657const char *
1658strsignal(sig)
1659int sig;
1660{
1661 static char buf[64];
1662
1663 if (sig < 1 || sig >= NSIG) {
1664 sprintf(buf, "Unknown signal %d", sig);
1665 return buf;
1666 }
1667#ifdef HAVE__SYS_SIGLIST
1668 return _sys_siglist[sig];
1669#else
1670 return sys_siglist[sig];
1671#endif
1672}
1673
1674#endif /* HAVE_STRSIGNAL */
1675
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001676#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
1678static void
1679rebuild_pollv()
1680{
1681 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001682
Roland McGrathee9d4352002-12-18 04:16:10 +00001683 if (pollv != NULL)
1684 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001685 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001686 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001687 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001688 exit(1);
1689 }
1690
Roland McGrathca16be82003-01-10 19:55:28 +00001691 for (i = j = 0; i < tcbtabsize; i++) {
1692 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 if (!(tcp->flags & TCB_INUSE))
1694 continue;
1695 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001696 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 j++;
1698 }
1699 if (j != nprocs) {
1700 fprintf(stderr, "strace: proc miscount\n");
1701 exit(1);
1702 }
1703}
1704
1705#ifndef HAVE_POLLABLE_PROCFS
1706
1707static void
1708proc_poll_open()
1709{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710 int i;
1711
1712 if (pipe(proc_poll_pipe) < 0) {
1713 perror("pipe");
1714 exit(1);
1715 }
1716 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001717 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 exit(1);
1719 }
1720 }
1721}
1722
1723static int
1724proc_poll(pollv, nfds, timeout)
1725struct pollfd *pollv;
1726int nfds;
1727int timeout;
1728{
1729 int i;
1730 int n;
1731 struct proc_pollfd pollinfo;
1732
1733 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1734 return n;
1735 if (n != sizeof(struct proc_pollfd)) {
1736 fprintf(stderr, "panic: short read: %d\n", n);
1737 exit(1);
1738 }
1739 for (i = 0; i < nprocs; i++) {
1740 if (pollv[i].fd == pollinfo.fd)
1741 pollv[i].revents = pollinfo.revents;
1742 else
1743 pollv[i].revents = 0;
1744 }
1745 poller_pid = pollinfo.pid;
1746 return 1;
1747}
1748
1749static void
1750wakeup_handler(sig)
1751int sig;
1752{
1753}
1754
1755static void
1756proc_poller(pfd)
1757int pfd;
1758{
1759 struct proc_pollfd pollinfo;
1760 struct sigaction sa;
1761 sigset_t blocked_set, empty_set;
1762 int i;
1763 int n;
1764 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001765#ifdef FREEBSD
1766 struct procfs_status pfs;
1767#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768
1769 switch (fork()) {
1770 case -1:
1771 perror("fork");
1772 _exit(0);
1773 case 0:
1774 break;
1775 default:
1776 return;
1777 }
1778
1779 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1780 sa.sa_flags = 0;
1781 sigemptyset(&sa.sa_mask);
1782 sigaction(SIGHUP, &sa, NULL);
1783 sigaction(SIGINT, &sa, NULL);
1784 sigaction(SIGQUIT, &sa, NULL);
1785 sigaction(SIGPIPE, &sa, NULL);
1786 sigaction(SIGTERM, &sa, NULL);
1787 sa.sa_handler = wakeup_handler;
1788 sigaction(SIGUSR1, &sa, NULL);
1789 sigemptyset(&blocked_set);
1790 sigaddset(&blocked_set, SIGUSR1);
1791 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1792 sigemptyset(&empty_set);
1793
1794 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1795 perror("getrlimit(RLIMIT_NOFILE, ...)");
1796 _exit(0);
1797 }
1798 n = rl.rlim_cur;
1799 for (i = 0; i < n; i++) {
1800 if (i != pfd && i != proc_poll_pipe[1])
1801 close(i);
1802 }
1803
1804 pollinfo.fd = pfd;
1805 pollinfo.pid = getpid();
1806 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001807#ifndef FREEBSD
1808 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1809#else /* FREEBSD */
1810 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1811#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001812 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813 switch (errno) {
1814 case EINTR:
1815 continue;
1816 case EBADF:
1817 pollinfo.revents = POLLERR;
1818 break;
1819 case ENOENT:
1820 pollinfo.revents = POLLHUP;
1821 break;
1822 default:
1823 perror("proc_poller: PIOCWSTOP");
1824 }
1825 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1826 _exit(0);
1827 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001828 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1830 sigsuspend(&empty_set);
1831 }
1832}
1833
1834#endif /* !HAVE_POLLABLE_PROCFS */
1835
1836static int
1837choose_pfd()
1838{
1839 int i, j;
1840 struct tcb *tcp;
1841
1842 static int last;
1843
1844 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001845 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846 /*
1847 * The previous process is ready to run again. We'll
1848 * let it do so if it is currently in a syscall. This
1849 * heuristic improves the readability of the trace.
1850 */
1851 tcp = pfd2tcb(pollv[last].fd);
1852 if (tcp && (tcp->flags & TCB_INSYSCALL))
1853 return pollv[last].fd;
1854 }
1855
1856 for (i = 0; i < nprocs; i++) {
1857 /* Let competing children run round robin. */
1858 j = (i + last + 1) % nprocs;
1859 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1860 tcp = pfd2tcb(pollv[j].fd);
1861 if (!tcp) {
1862 fprintf(stderr, "strace: lost proc\n");
1863 exit(1);
1864 }
1865 droptcb(tcp);
1866 return -1;
1867 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001868 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869 last = j;
1870 return pollv[j].fd;
1871 }
1872 }
1873 fprintf(stderr, "strace: nothing ready\n");
1874 exit(1);
1875}
1876
1877static int
1878trace()
1879{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001880#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001881 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001882#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 struct tcb *tcp;
1884 int pfd;
1885 int what;
1886 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001887 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001888
1889 for (;;) {
1890 if (interactive)
1891 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1892
1893 if (nprocs == 0)
1894 break;
1895
1896 switch (nprocs) {
1897 case 1:
1898#ifndef HAVE_POLLABLE_PROCFS
1899 if (proc_poll_pipe[0] == -1) {
1900#endif
1901 tcp = pid2tcb(0);
1902 if (!tcp)
1903 continue;
1904 pfd = tcp->pfd;
1905 if (pfd == -1)
1906 continue;
1907 break;
1908#ifndef HAVE_POLLABLE_PROCFS
1909 }
1910 /* fall through ... */
1911#endif /* !HAVE_POLLABLE_PROCFS */
1912 default:
1913#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001914#ifdef POLL_HACK
1915 /* On some systems (e.g. UnixWare) we get too much ugly
1916 "unfinished..." stuff when multiple proceses are in
1917 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001918
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001919 if (in_syscall) {
1920 struct pollfd pv;
1921 tcp = in_syscall;
1922 in_syscall = NULL;
1923 pv.fd = tcp->pfd;
1924 pv.events = POLLWANT;
1925 if ((what = poll (&pv, 1, 1)) < 0) {
1926 if (interrupted)
1927 return 0;
1928 continue;
1929 }
1930 else if (what == 1 && pv.revents & POLLWANT) {
1931 goto FOUND;
1932 }
1933 }
1934#endif
1935
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 if (poll(pollv, nprocs, INFTIM) < 0) {
1937 if (interrupted)
1938 return 0;
1939 continue;
1940 }
1941#else /* !HAVE_POLLABLE_PROCFS */
1942 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1943 if (interrupted)
1944 return 0;
1945 continue;
1946 }
1947#endif /* !HAVE_POLLABLE_PROCFS */
1948 pfd = choose_pfd();
1949 if (pfd == -1)
1950 continue;
1951 break;
1952 }
1953
1954 /* Look up `pfd' in our table. */
1955 if ((tcp = pfd2tcb(pfd)) == NULL) {
1956 fprintf(stderr, "unknown pfd: %u\n", pfd);
1957 exit(1);
1958 }
John Hughesb6643082002-05-23 11:02:22 +00001959#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001960 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001961#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962 /* Get the status of the process. */
1963 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001964#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001965 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001966#else /* FREEBSD */
1967 /* Thanks to some scheduling mystery, the first poller
1968 sometimes waits for the already processed end of fork
1969 event. Doing a non blocking poll here solves the problem. */
1970 if (proc_poll_pipe[0] != -1)
1971 ioctl_result = IOCTL_STATUS (tcp);
1972 else
1973 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001974#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 ioctl_errno = errno;
1976#ifndef HAVE_POLLABLE_PROCFS
1977 if (proc_poll_pipe[0] != -1) {
1978 if (ioctl_result < 0)
1979 kill(poller_pid, SIGKILL);
1980 else
1981 kill(poller_pid, SIGUSR1);
1982 }
1983#endif /* !HAVE_POLLABLE_PROCFS */
1984 }
1985 if (interrupted)
1986 return 0;
1987
1988 if (interactive)
1989 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1990
1991 if (ioctl_result < 0) {
1992 /* Find out what happened if it failed. */
1993 switch (ioctl_errno) {
1994 case EINTR:
1995 case EBADF:
1996 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001997#ifdef FREEBSD
1998 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001999#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 case ENOENT:
2001 droptcb(tcp);
2002 continue;
2003 default:
2004 perror("PIOCWSTOP");
2005 exit(1);
2006 }
2007 }
2008
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002009#ifdef FREEBSD
2010 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2011 /* discard first event for a syscall we never entered */
2012 IOCTL (tcp->pfd, PIOCRUN, 0);
2013 continue;
2014 }
Roland McGrath553a6092002-12-16 20:40:39 +00002015#endif
2016
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017 /* clear the just started flag */
2018 tcp->flags &= ~TCB_STARTUP;
2019
2020 /* set current output file */
2021 outf = tcp->outf;
2022
2023 if (cflag) {
2024 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002025#ifdef FREEBSD
2026 char buf[1024];
2027 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002029 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2030 buf[len] = '\0';
2031 sscanf(buf,
2032 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2033 &stime.tv_sec, &stime.tv_usec);
2034 } else
2035 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002036#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2038 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002039#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2041 tcp->stime = stime;
2042 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002043 what = tcp->status.PR_WHAT;
2044 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002045#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002047 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2048 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049 if (trace_syscall(tcp) < 0) {
2050 fprintf(stderr, "syscall trouble\n");
2051 exit(1);
2052 }
2053 }
2054 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002055#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002057#ifdef POLL_HACK
2058 in_syscall = tcp;
2059#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002060 case PR_SYSEXIT:
2061 if (trace_syscall(tcp) < 0) {
2062 fprintf(stderr, "syscall trouble\n");
2063 exit(1);
2064 }
2065 break;
2066 case PR_SIGNALLED:
2067 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2068 printleader(tcp);
2069 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002070 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002071 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002072#ifdef PR_INFO
2073 if (tcp->status.PR_INFO.si_signo == what) {
2074 printleader(tcp);
2075 tprintf(" siginfo=");
2076 printsiginfo(&tcp->status.PR_INFO, 1);
2077 printtrailer(tcp);
2078 }
2079#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080 }
2081 break;
2082 case PR_FAULTED:
2083 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2084 printleader(tcp);
2085 tprintf("=== FAULT %d ===", what);
2086 printtrailer(tcp);
2087 }
2088 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002089#ifdef FREEBSD
2090 case 0: /* handle case we polled for nothing */
2091 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002092#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002093 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002094 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 exit(1);
2096 break;
2097 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002098 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002099#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002100 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002101#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002102 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002103#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104 perror("PIOCRUN");
2105 exit(1);
2106 }
2107 }
2108 return 0;
2109}
2110
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002111#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002113#ifdef TCB_GROUP_EXITING
2114/* Handle an exit detach or death signal that is taking all the
2115 related clone threads with it. This is called in three circumstances:
2116 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2117 SIG == 0 Continuing TCP will perform an exit_group syscall.
2118 SIG == other Continuing TCP with SIG will kill the process.
2119*/
2120static int
2121handle_group_exit(struct tcb *tcp, int sig)
2122{
2123 /* We need to locate our records of all the clone threads
2124 related to TCP, either its children or siblings. */
2125 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2126 ? tcp->parent
2127 : tcp->nclone_detached > 0
2128 ? tcp : NULL);
2129
2130 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002131 if (leader != NULL && leader != tcp &&
2132 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002133 fprintf(stderr,
2134 "PANIC: handle_group_exit: %d leader %d\n",
2135 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002136 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002137#ifndef USE_PROCFS
2138 resume_from_tcp (tcp);
2139#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002140 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002141 }
2142 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002143 /* Mark that we are taking the process down. */
2144 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002145 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002146 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002147 if (leader != NULL && leader != tcp)
2148 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002149 }
2150 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2151 perror("strace: ptrace(PTRACE_CONT, ...)");
2152 cleanup();
2153 return -1;
2154 }
2155 else {
Roland McGrath05690952004-10-20 01:00:27 +00002156 if (leader != NULL)
2157 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002158 if (leader != NULL && leader != tcp)
2159 droptcb(tcp);
2160 /* The leader will report to us as parent now,
2161 and then we'll get to the SIG==-1 case. */
2162 return 0;
2163 }
2164 }
2165
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002166 return 0;
2167}
2168#endif
2169
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170static int
2171trace()
2172{
2173 int pid;
2174 int wait_errno;
2175 int status;
2176 struct tcb *tcp;
2177#ifdef LINUX
2178 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002179#ifdef __WALL
2180 static int wait4_options = __WALL;
2181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182#endif /* LINUX */
2183
2184 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002185 if (interrupted)
2186 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 if (interactive)
2188 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2189#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002190#ifdef __WALL
2191 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002192 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002193 /* this kernel does not support __WALL */
2194 wait4_options &= ~__WALL;
2195 errno = 0;
2196 pid = wait4(-1, &status, wait4_options,
2197 cflag ? &ru : NULL);
2198 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002199 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002200 /* most likely a "cloned" process */
2201 pid = wait4(-1, &status, __WCLONE,
2202 cflag ? &ru : NULL);
2203 if (pid == -1) {
2204 fprintf(stderr, "strace: clone wait4 "
2205 "failed: %s\n", strerror(errno));
2206 }
2207 }
2208#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002210#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211#endif /* LINUX */
2212#ifdef SUNOS4
2213 pid = wait(&status);
2214#endif /* SUNOS4 */
2215 wait_errno = errno;
2216 if (interactive)
2217 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2218
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002219 if (pid == -1) {
2220 switch (wait_errno) {
2221 case EINTR:
2222 continue;
2223 case ECHILD:
2224 /*
2225 * We would like to verify this case
2226 * but sometimes a race in Solbourne's
2227 * version of SunOS sometimes reports
2228 * ECHILD before sending us SIGCHILD.
2229 */
2230#if 0
2231 if (nprocs == 0)
2232 return 0;
2233 fprintf(stderr, "strace: proc miscount\n");
2234 exit(1);
2235#endif
2236 return 0;
2237 default:
2238 errno = wait_errno;
2239 perror("strace: wait");
2240 return -1;
2241 }
2242 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002243 if (pid == popen_pid) {
2244 if (WIFEXITED(status) || WIFSIGNALED(status))
2245 popen_pid = -1;
2246 continue;
2247 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248 if (debug)
2249 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2250
2251 /* Look up `pid' in our table. */
2252 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002253#ifdef LINUX
2254 if (followfork || followvfork) {
2255 /* This is needed to go with the CLONE_PTRACE
2256 changes in process.c/util.c: we might see
2257 the child's initial trap before we see the
2258 parent return from the clone syscall.
2259 Leave the child suspended until the parent
2260 returns from its system call. Only then
2261 will we have the association of parent and
2262 child so that we know how to do clearbpt
2263 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002264 if (nprocs == tcbtabsize &&
2265 expand_tcbtab())
2266 tcp = NULL;
2267 else
2268 tcp = alloctcb(pid);
2269 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002270 kill(pid, SIGKILL); /* XXX */
2271 return 0;
2272 }
2273 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002274 if (!qflag)
2275 fprintf(stderr, "\
2276Process %d attached (waiting for parent)\n",
2277 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002278 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002279 else
2280 /* This can happen if a clone call used
2281 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002282#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002283 {
2284 fprintf(stderr, "unknown pid: %u\n", pid);
2285 if (WIFSTOPPED(status))
2286 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2287 exit(1);
2288 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289 }
2290 /* set current output file */
2291 outf = tcp->outf;
2292 if (cflag) {
2293#ifdef LINUX
2294 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2295 tcp->stime = ru.ru_stime;
2296#endif /* !LINUX */
2297 }
2298
2299 if (tcp->flags & TCB_SUSPENDED) {
2300 /*
2301 * Apparently, doing any ptrace() call on a stopped
2302 * process, provokes the kernel to report the process
2303 * status again on a subsequent wait(), even if the
2304 * process has not been actually restarted.
2305 * Since we have inspected the arguments of suspended
2306 * processes we end up here testing for this case.
2307 */
2308 continue;
2309 }
2310 if (WIFSIGNALED(status)) {
2311 if (!cflag
2312 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2313 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002314 tprintf("+++ killed by %s %s+++",
2315 signame(WTERMSIG(status)),
2316#ifdef WCOREDUMP
2317 WCOREDUMP(status) ? "(core dumped) " :
2318#endif
2319 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002320 printtrailer(tcp);
2321 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002322#ifdef TCB_GROUP_EXITING
2323 handle_group_exit(tcp, -1);
2324#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002325 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002326#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002327 continue;
2328 }
2329 if (WIFEXITED(status)) {
2330 if (debug)
2331 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002332 if ((tcp->flags & TCB_ATTACHED)
2333#ifdef TCB_GROUP_EXITING
2334 && !(tcp->parent && (tcp->parent->flags &
2335 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002336 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002337#endif
2338 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002339 fprintf(stderr,
2340 "PANIC: attached pid %u exited\n",
2341 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002342 if (tcp == tcp_last) {
2343 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2344 == TCB_INSYSCALL)
2345 tprintf(" <unfinished ... exit status %d>\n",
2346 WEXITSTATUS(status));
2347 tcp_last = NULL;
2348 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002349#ifdef TCB_GROUP_EXITING
2350 handle_group_exit(tcp, -1);
2351#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002353#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002354 continue;
2355 }
2356 if (!WIFSTOPPED(status)) {
2357 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2358 droptcb(tcp);
2359 continue;
2360 }
2361 if (debug)
2362 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002363 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002364
Roland McGrath02203312007-06-11 22:06:31 +00002365 /*
2366 * Interestingly, the process may stop
2367 * with STOPSIG equal to some other signal
2368 * than SIGSTOP if we happend to attach
2369 * just before the process takes a signal.
2370 */
2371 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002372 /*
2373 * This flag is there to keep us in sync.
2374 * Next time this process stops it should
2375 * really be entering a system call.
2376 */
2377 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002379 /*
2380 * One example is a breakpoint inherited from
2381 * parent through fork ().
2382 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002383 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2384 droptcb(tcp);
2385 cleanup();
2386 return -1;
2387 }
2388 }
2389 goto tracing;
2390 }
2391
2392 if (WSTOPSIG(status) != SIGTRAP) {
2393 if (WSTOPSIG(status) == SIGSTOP &&
2394 (tcp->flags & TCB_SIGTRAPPED)) {
2395 /*
2396 * Trapped attempt to block SIGTRAP
2397 * Hope we are back in control now.
2398 */
2399 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2400 if (ptrace(PTRACE_SYSCALL,
2401 pid, (char *) 1, 0) < 0) {
2402 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2403 cleanup();
2404 return -1;
2405 }
2406 continue;
2407 }
2408 if (!cflag
2409 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002410 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002411#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002412# define PSR_RI 41
2413 struct siginfo si;
2414 unsigned long psr;
2415
2416 upeek(pid, PT_CR_IPSR, &psr);
2417 upeek(pid, PT_CR_IIP, &pc);
2418
2419 pc += (psr >> PSR_RI) & 0x3;
2420 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2421 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002422#elif defined PTRACE_GETSIGINFO
2423 if (WSTOPSIG(status) == SIGSEGV ||
2424 WSTOPSIG(status) == SIGBUS) {
2425 siginfo_t si;
2426 if (ptrace(PTRACE_GETSIGINFO, pid,
2427 0, &si) == 0)
2428 addr = (unsigned long)
2429 si.si_addr;
2430 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002431#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002432 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002433 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002434 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002435 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002436 printtrailer(tcp);
2437 }
Roland McGrath05690952004-10-20 01:00:27 +00002438 if (((tcp->flags & TCB_ATTACHED) ||
2439 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002440 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002441#ifdef TCB_GROUP_EXITING
2442 handle_group_exit(tcp, WSTOPSIG(status));
2443#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002445#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002446 continue;
2447 }
2448 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2449 WSTOPSIG(status)) < 0) {
2450 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2451 cleanup();
2452 return -1;
2453 }
2454 tcp->flags &= ~TCB_SUSPENDED;
2455 continue;
2456 }
Roland McGrath02203312007-06-11 22:06:31 +00002457 /* we handled the STATUS, we are permitted to interrupt now. */
2458 if (interrupted)
2459 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002460 if (trace_syscall(tcp) < 0) {
2461 if (tcp->flags & TCB_ATTACHED)
2462 detach(tcp, 0);
2463 else {
2464 ptrace(PTRACE_KILL,
2465 tcp->pid, (char *) 1, SIGTERM);
2466 droptcb(tcp);
2467 }
2468 continue;
2469 }
2470 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002471#ifdef TCB_GROUP_EXITING
2472 if (tcp->flags & TCB_GROUP_EXITING) {
2473 if (handle_group_exit(tcp, 0) < 0)
2474 return -1;
2475 continue;
2476 }
2477#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478 if (tcp->flags & TCB_ATTACHED)
2479 detach(tcp, 0);
2480 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2481 perror("strace: ptrace(PTRACE_CONT, ...)");
2482 cleanup();
2483 return -1;
2484 }
2485 continue;
2486 }
2487 if (tcp->flags & TCB_SUSPENDED) {
2488 if (!qflag)
2489 fprintf(stderr, "Process %u suspended\n", pid);
2490 continue;
2491 }
2492 tracing:
2493 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2494 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2495 cleanup();
2496 return -1;
2497 }
2498 }
2499 return 0;
2500}
2501
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002502#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002503
2504static int curcol;
2505
2506#ifdef __STDC__
2507#include <stdarg.h>
2508#define VA_START(a, b) va_start(a, b)
2509#else
2510#include <varargs.h>
2511#define VA_START(a, b) va_start(a)
2512#endif
2513
2514void
2515#ifdef __STDC__
2516tprintf(const char *fmt, ...)
2517#else
2518tprintf(fmt, va_alist)
2519char *fmt;
2520va_dcl
2521#endif
2522{
2523 va_list args;
2524
2525 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002526 if (outf) {
2527 int n = vfprintf(outf, fmt, args);
2528 if (n < 0 && outf != stderr)
2529 perror(outfname == NULL
2530 ? "<writing to pipe>" : outfname);
2531 else
2532 curcol += n;
2533 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 va_end(args);
2535 return;
2536}
2537
2538void
2539printleader(tcp)
2540struct tcb *tcp;
2541{
2542 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2543 tcp_last->flags |= TCB_REPRINT;
2544 tprintf(" <unfinished ...>\n");
2545 }
2546 curcol = 0;
2547 if ((followfork == 1 || pflag_seen > 1) && outfname)
2548 tprintf("%-5d ", tcp->pid);
2549 else if (nprocs > 1 && !outfname)
2550 tprintf("[pid %5u] ", tcp->pid);
2551 if (tflag) {
2552 char str[sizeof("HH:MM:SS")];
2553 struct timeval tv, dtv;
2554 static struct timeval otv;
2555
2556 gettimeofday(&tv, NULL);
2557 if (rflag) {
2558 if (otv.tv_sec == 0)
2559 otv = tv;
2560 tv_sub(&dtv, &tv, &otv);
2561 tprintf("%6ld.%06ld ",
2562 (long) dtv.tv_sec, (long) dtv.tv_usec);
2563 otv = tv;
2564 }
2565 else if (tflag > 2) {
2566 tprintf("%ld.%06ld ",
2567 (long) tv.tv_sec, (long) tv.tv_usec);
2568 }
2569 else {
2570 time_t local = tv.tv_sec;
2571 strftime(str, sizeof(str), "%T", localtime(&local));
2572 if (tflag > 1)
2573 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2574 else
2575 tprintf("%s ", str);
2576 }
2577 }
2578 if (iflag)
2579 printcall(tcp);
2580}
2581
2582void
2583tabto(col)
2584int col;
2585{
2586 if (curcol < col)
2587 tprintf("%*s", col - curcol, "");
2588}
2589
2590void
2591printtrailer(tcp)
2592struct tcb *tcp;
2593{
2594 tprintf("\n");
2595 tcp_last = NULL;
2596}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002597
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002598#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002599
2600int mp_ioctl (int fd, int cmd, void *arg, int size) {
2601
2602 struct iovec iov[2];
2603 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002604
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002605 iov[0].iov_base = &cmd;
2606 iov[0].iov_len = sizeof cmd;
2607 if (arg) {
2608 ++n;
2609 iov[1].iov_base = arg;
2610 iov[1].iov_len = size;
2611 }
Roland McGrath553a6092002-12-16 20:40:39 +00002612
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002613 return writev (fd, iov, n);
2614}
2615
2616#endif