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