blob: 9d82f586eaccd34c328d872795253170114845da [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 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000820
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821 sigemptyset(&empty_set);
822 sigemptyset(&blocked_set);
823 sa.sa_handler = SIG_IGN;
824 sigemptyset(&sa.sa_mask);
825 sa.sa_flags = 0;
826 sigaction(SIGTTOU, &sa, NULL);
827 sigaction(SIGTTIN, &sa, NULL);
828 if (interactive) {
829 sigaddset(&blocked_set, SIGHUP);
830 sigaddset(&blocked_set, SIGINT);
831 sigaddset(&blocked_set, SIGQUIT);
832 sigaddset(&blocked_set, SIGPIPE);
833 sigaddset(&blocked_set, SIGTERM);
834 sa.sa_handler = interrupt;
835#ifdef SUNOS4
836 /* POSIX signals on sunos4.1 are a little broken. */
837 sa.sa_flags = SA_INTERRUPT;
838#endif /* SUNOS4 */
839 }
840 sigaction(SIGHUP, &sa, NULL);
841 sigaction(SIGINT, &sa, NULL);
842 sigaction(SIGQUIT, &sa, NULL);
843 sigaction(SIGPIPE, &sa, NULL);
844 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000845#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000846 sa.sa_handler = reaper;
847 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000848#else
849 /* Make sure SIGCHLD has the default action so that waitpid
850 definitely works without losing track of children. The user
851 should not have given us a bogus state to inherit, but he might
852 have. Arguably we should detect SIG_IGN here and pass it on
853 to children, but probably noone really needs that. */
854 sa.sa_handler = SIG_DFL;
855 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000856#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000857
Roland McGrath02203312007-06-11 22:06:31 +0000858 if (pflag_seen)
859 startup_attach();
860 else
861 startup_child(&argv[optind]);
862
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863 if (trace() < 0)
864 exit(1);
865 cleanup();
866 exit(0);
867}
868
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000869int
870expand_tcbtab()
871{
872 /* Allocate some more TCBs and expand the table.
873 We don't want to relocate the TCBs because our
874 callers have pointers and it would be a pain.
875 So tcbtab is a table of pointers. Since we never
876 free the TCBs, we allocate a single chunk of many. */
877 struct tcb **newtab = (struct tcb **)
878 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
879 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
880 sizeof *newtcbs);
881 int i;
882 if (newtab == NULL || newtcbs == NULL) {
883 if (newtab != NULL)
884 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000885 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
886 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000887 return 1;
888 }
889 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
890 newtab[i] = &newtcbs[i - tcbtabsize];
891 tcbtabsize *= 2;
892 tcbtab = newtab;
893
894 return 0;
895}
896
897
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000899alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900{
901 int i;
902 struct tcb *tcp;
903
Roland McGrathee9d4352002-12-18 04:16:10 +0000904 for (i = 0; i < tcbtabsize; i++) {
905 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906 if ((tcp->flags & TCB_INUSE) == 0) {
907 tcp->pid = pid;
908 tcp->parent = NULL;
909 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000910 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000911#ifdef TCB_CLONE_THREAD
912 tcp->nclone_threads = tcp->nclone_detached = 0;
913 tcp->nclone_waiting = 0;
914#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915 tcp->flags = TCB_INUSE | TCB_STARTUP;
916 tcp->outf = outf; /* Initialise to current out file */
917 tcp->stime.tv_sec = 0;
918 tcp->stime.tv_usec = 0;
919 tcp->pfd = -1;
920 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000921 if (command_options_parsed)
922 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000923 return tcp;
924 }
925 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000926 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 return NULL;
928}
929
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000930#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931int
932proc_open(tcp, attaching)
933struct tcb *tcp;
934int attaching;
935{
936 char proc[32];
937 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000938#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000939 int i;
940 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 sigset_t signals;
942 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000943#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944#ifndef HAVE_POLLABLE_PROCFS
945 static int last_pfd;
946#endif
947
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000948#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000949 /* Open the process pseudo-files in /proc. */
950 sprintf(proc, "/proc/%d/ctl", tcp->pid);
951 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952 perror("strace: open(\"/proc/...\", ...)");
953 return -1;
954 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000955 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956 return -1;
957 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000958 sprintf(proc, "/proc/%d/status", tcp->pid);
959 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
960 perror("strace: open(\"/proc/...\", ...)");
961 return -1;
962 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000963 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000964 return -1;
965 }
966 sprintf(proc, "/proc/%d/as", tcp->pid);
967 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
968 perror("strace: open(\"/proc/...\", ...)");
969 return -1;
970 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000971 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000972 return -1;
973 }
974#else
975 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000976#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000977 sprintf(proc, "/proc/%d", tcp->pid);
978 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000979#else /* FREEBSD */
980 sprintf(proc, "/proc/%d/mem", tcp->pid);
981 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
982#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000983 perror("strace: open(\"/proc/...\", ...)");
984 return -1;
985 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000986 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000987 return -1;
988 }
989#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000990#ifdef FREEBSD
991 sprintf(proc, "/proc/%d/regs", tcp->pid);
992 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
993 perror("strace: open(\"/proc/.../regs\", ...)");
994 return -1;
995 }
996 if (cflag) {
997 sprintf(proc, "/proc/%d/status", tcp->pid);
998 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
999 perror("strace: open(\"/proc/.../status\", ...)");
1000 return -1;
1001 }
1002 } else
1003 tcp->pfd_status = -1;
1004#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001005 rebuild_pollv();
1006 if (!attaching) {
1007 /*
1008 * Wait for the child to pause. Because of a race
1009 * condition we have to poll for the event.
1010 */
1011 for (;;) {
1012 if (IOCTL_STATUS (tcp) < 0) {
1013 perror("strace: PIOCSTATUS");
1014 return -1;
1015 }
1016 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001017 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001018 }
1019 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001020#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001021 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001022 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001023 perror("strace: PIOCSTOP");
1024 return -1;
1025 }
Roland McGrath553a6092002-12-16 20:40:39 +00001026#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027#ifdef PIOCSET
1028 /* Set Run-on-Last-Close. */
1029 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001030 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 perror("PIOCSET PR_RLC");
1032 return -1;
1033 }
1034 /* Set or Reset Inherit-on-Fork. */
1035 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001036 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 perror("PIOC{SET,RESET} PR_FORK");
1038 return -1;
1039 }
1040#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001041#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1043 perror("PIOCSRLC");
1044 return -1;
1045 }
1046 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1047 perror("PIOC{S,R}FORK");
1048 return -1;
1049 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050#else /* FREEBSD */
1051 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1052 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1053 perror("PIOCGFL");
1054 return -1;
1055 }
1056 arg &= ~PF_LINGER;
1057 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1058 perror("PIOCSFL");
1059 return -1;
1060 }
1061#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001063#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001064 /* Enable all syscall entries we care about. */
1065 premptyset(&syscalls);
1066 for (i = 1; i < MAX_QUALS; ++i) {
1067 if (i > (sizeof syscalls) * CHAR_BIT) break;
1068 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1069 }
1070 praddset (&syscalls, SYS_execve);
1071 if (followfork) {
1072 praddset (&syscalls, SYS_fork);
1073#ifdef SYS_forkall
1074 praddset (&syscalls, SYS_forkall);
1075#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001076#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001077 praddset (&syscalls, SYS_fork1);
1078#endif
1079#ifdef SYS_rfork1
1080 praddset (&syscalls, SYS_rfork1);
1081#endif
1082#ifdef SYS_rforkall
1083 praddset (&syscalls, SYS_rforkall);
1084#endif
1085 }
1086 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 perror("PIOCSENTRY");
1088 return -1;
1089 }
John Hughes19e49982001-10-19 08:59:12 +00001090 /* Enable the syscall exits. */
1091 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 perror("PIOSEXIT");
1093 return -1;
1094 }
John Hughes19e49982001-10-19 08:59:12 +00001095 /* Enable signals we care about. */
1096 premptyset(&signals);
1097 for (i = 1; i < MAX_QUALS; ++i) {
1098 if (i > (sizeof signals) * CHAR_BIT) break;
1099 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1100 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001101 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001102 perror("PIOCSTRACE");
1103 return -1;
1104 }
John Hughes19e49982001-10-19 08:59:12 +00001105 /* Enable faults we care about */
1106 premptyset(&faults);
1107 for (i = 1; i < MAX_QUALS; ++i) {
1108 if (i > (sizeof faults) * CHAR_BIT) break;
1109 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1110 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001111 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 perror("PIOCSFAULT");
1113 return -1;
1114 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001115#else /* FREEBSD */
1116 /* set events flags. */
1117 arg = S_SIG | S_SCE | S_SCX ;
1118 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1119 perror("PIOCBIS");
1120 return -1;
1121 }
1122#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 if (!attaching) {
1124#ifdef MIPS
1125 /*
1126 * The SGI PRSABORT doesn't work for pause() so
1127 * we send it a caught signal to wake it up.
1128 */
1129 kill(tcp->pid, SIGINT);
1130#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001131#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001133 arg = PRSABORT;
1134 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 perror("PIOCRUN");
1136 return -1;
1137 }
Roland McGrath553a6092002-12-16 20:40:39 +00001138#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001139#endif /* !MIPS*/
1140#ifdef FREEBSD
1141 /* wake up the child if it received the SIGSTOP */
1142 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001143#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 for (;;) {
1145 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001146 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 perror("PIOCWSTOP");
1148 return -1;
1149 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001150 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001151 tcp->flags &= ~TCB_INSYSCALL;
1152 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001153 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 break;
1155 }
1156 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001157#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001158 arg = 0;
1159 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001160#else /* FREEBSD */
1161 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001162#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 perror("PIOCRUN");
1164 return -1;
1165 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001166#ifdef FREEBSD
1167 /* handle the case where we "opened" the child before
1168 it did the kill -STOP */
1169 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1170 tcp->status.PR_WHAT == SIGSTOP)
1171 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001172#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001174#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001176#else /* FREEBSD */
1177 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001178 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001179 /* We are attaching to an already running process.
1180 * Try to figure out the state of the process in syscalls,
1181 * to handle the first event well.
1182 * This is done by having a look at the "wchan" property of the
1183 * process, which tells where it is stopped (if it is). */
1184 FILE * status;
1185 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001186
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001187 sprintf(proc, "/proc/%d/status", tcp->pid);
1188 status = fopen(proc, "r");
1189 if (status &&
1190 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1191 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1192 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1193 strcmp(wchan, "stopevent")) {
1194 /* The process is asleep in the middle of a syscall.
1195 Fake the syscall entry event */
1196 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1197 tcp->status.PR_WHY = PR_SYSENTRY;
1198 trace_syscall(tcp);
1199 }
1200 if (status)
1201 fclose(status);
1202 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001203 }
1204#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205#ifndef HAVE_POLLABLE_PROCFS
1206 if (proc_poll_pipe[0] != -1)
1207 proc_poller(tcp->pfd);
1208 else if (nprocs > 1) {
1209 proc_poll_open();
1210 proc_poller(last_pfd);
1211 proc_poller(tcp->pfd);
1212 }
1213 last_pfd = tcp->pfd;
1214#endif /* !HAVE_POLLABLE_PROCFS */
1215 return 0;
1216}
1217
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001218#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001220struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221pid2tcb(pid)
1222int pid;
1223{
1224 int i;
1225 struct tcb *tcp;
1226
Roland McGrathee9d4352002-12-18 04:16:10 +00001227 for (i = 0; i < tcbtabsize; i++) {
1228 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 if (pid && tcp->pid != pid)
1230 continue;
1231 if (tcp->flags & TCB_INUSE)
1232 return tcp;
1233 }
1234 return NULL;
1235}
1236
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001237#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238
1239static struct tcb *
1240pfd2tcb(pfd)
1241int pfd;
1242{
1243 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244
Roland McGrathca16be82003-01-10 19:55:28 +00001245 for (i = 0; i < tcbtabsize; i++) {
1246 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247 if (tcp->pfd != pfd)
1248 continue;
1249 if (tcp->flags & TCB_INUSE)
1250 return tcp;
1251 }
1252 return NULL;
1253}
1254
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001255#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256
1257void
1258droptcb(tcp)
1259struct tcb *tcp;
1260{
1261 if (tcp->pid == 0)
1262 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001263#ifdef TCB_CLONE_THREAD
1264 if (tcp->nclone_threads > 0) {
1265 /* There are other threads left in this process, but this
1266 is the one whose PID represents the whole process.
1267 We need to keep this record around as a zombie until
1268 all the threads die. */
1269 tcp->flags |= TCB_EXITING;
1270 return;
1271 }
1272#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001273 nprocs--;
1274 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001275
Roland McGrathe29341c2003-01-10 20:14:20 +00001276 if (tcp->parent != NULL) {
1277 tcp->parent->nchildren--;
1278#ifdef TCB_CLONE_THREAD
1279 if (tcp->flags & TCB_CLONE_DETACHED)
1280 tcp->parent->nclone_detached--;
1281 if (tcp->flags & TCB_CLONE_THREAD)
1282 tcp->parent->nclone_threads--;
1283#endif
Roland McGrath09623452003-05-23 02:27:13 +00001284#ifdef TCB_CLONE_DETACHED
1285 if (!(tcp->flags & TCB_CLONE_DETACHED))
1286#endif
1287 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001288 tcp->parent = NULL;
1289 }
1290
1291 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 if (tcp->pfd != -1) {
1293 close(tcp->pfd);
1294 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001295#ifdef FREEBSD
1296 if (tcp->pfd_reg != -1) {
1297 close(tcp->pfd_reg);
1298 tcp->pfd_reg = -1;
1299 }
1300 if (tcp->pfd_status != -1) {
1301 close(tcp->pfd_status);
1302 tcp->pfd_status = -1;
1303 }
Roland McGrath553a6092002-12-16 20:40:39 +00001304#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001305#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001306 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307#endif
1308 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001309
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001310 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001312
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 tcp->outf = 0;
1314}
1315
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001316#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001317
1318static int
1319resume(tcp)
1320struct tcb *tcp;
1321{
1322 if (tcp == NULL)
1323 return -1;
1324
1325 if (!(tcp->flags & TCB_SUSPENDED)) {
1326 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1327 return -1;
1328 }
1329 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001330#ifdef TCB_CLONE_THREAD
1331 if (tcp->flags & TCB_CLONE_THREAD)
1332 tcp->parent->nclone_waiting--;
1333#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334
1335 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1336 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1337 return -1;
1338 }
1339
1340 if (!qflag)
1341 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1342 return 0;
1343}
1344
Roland McGrath1bfd3102007-08-03 10:02:00 +00001345static int
1346resume_from_tcp (struct tcb *tcp)
1347{
1348 int error = 0;
1349 int resumed = 0;
1350
1351 /* XXX This won't always be quite right (but it never was).
1352 A waiter with argument 0 or < -1 is waiting for any pid in
1353 a particular pgrp, which this child might or might not be
1354 in. The waiter will only wake up if it's argument is -1
1355 or if it's waiting for tcp->pid's pgrp. It makes a
1356 difference to wake up a waiter when there might be more
1357 traced children, because it could get a false ECHILD
1358 error. OTOH, if this was the last child in the pgrp, then
1359 it ought to wake up and get ECHILD. We would have to
1360 search the system for all pid's in the pgrp to be sure.
1361
1362 && (t->waitpid == -1 ||
1363 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1364 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1365 */
1366
1367 if (tcp->parent &&
1368 (tcp->parent->flags & TCB_SUSPENDED) &&
1369 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1370 error = resume(tcp->parent);
1371 ++resumed;
1372 }
1373#ifdef TCB_CLONE_THREAD
1374 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1375 /* Some other threads of our parent are waiting too. */
1376 unsigned int i;
1377
1378 /* Resume all the threads that were waiting for this PID. */
1379 for (i = 0; i < tcbtabsize; i++) {
1380 struct tcb *t = tcbtab[i];
1381 if (t->parent == tcp->parent && t != tcp
1382 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1383 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1384 && t->waitpid == tcp->pid) {
1385 error |= resume (t);
1386 ++resumed;
1387 }
1388 }
1389 if (resumed == 0)
1390 /* Noone was waiting for this PID in particular,
1391 so now we might need to resume some wildcarders. */
1392 for (i = 0; i < tcbtabsize; i++) {
1393 struct tcb *t = tcbtab[i];
1394 if (t->parent == tcp->parent && t != tcp
1395 && ((t->flags
1396 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1397 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1398 && t->waitpid <= 0
1399 ) {
1400 error |= resume (t);
1401 break;
1402 }
1403 }
1404 }
1405
1406 return error;
1407}
1408#endif
1409
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001410#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411
Roland McGrath0a463882007-07-05 18:43:16 +00001412/* detach traced process; continue with sig
1413 Never call DETACH twice on the same process as both unattached and
1414 attached-unstopped processes give the same ESRCH. For unattached process we
1415 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416
1417static int
1418detach(tcp, sig)
1419struct tcb *tcp;
1420int sig;
1421{
1422 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001423#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001424 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001425 struct tcb *zombie = NULL;
1426
1427 /* If the group leader is lingering only because of this other
1428 thread now dying, then detach the leader as well. */
1429 if ((tcp->flags & TCB_CLONE_THREAD) &&
1430 tcp->parent->nclone_threads == 1 &&
1431 (tcp->parent->flags & TCB_EXITING))
1432 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001433#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434
1435 if (tcp->flags & TCB_BPTSET)
1436 sig = SIGKILL;
1437
1438#ifdef LINUX
1439 /*
1440 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001441 * before detaching. Arghh. We go through hoops
1442 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001444#if defined(SPARC)
1445#undef PTRACE_DETACH
1446#define PTRACE_DETACH PTRACE_SUNDETACH
1447#endif
Roland McGrath02203312007-06-11 22:06:31 +00001448 /*
1449 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1450 * expected SIGSTOP. We must catch exactly one as otherwise the
1451 * detached process would be left stopped (process state T).
1452 */
1453 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1455 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001456 }
1457 else if (errno != ESRCH) {
1458 /* Shouldn't happen. */
1459 perror("detach: ptrace(PTRACE_DETACH, ...)");
1460 }
Roland McGrath134813a2007-06-02 00:07:33 +00001461 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1462 : tcp->pid),
1463 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001464 if (errno != ESRCH)
1465 perror("detach: checking sanity");
1466 }
Roland McGrath02203312007-06-11 22:06:31 +00001467 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1468 ? tcp->parent->pid : tcp->pid),
1469 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001470 if (errno != ESRCH)
1471 perror("detach: stopping child");
1472 }
Roland McGrath02203312007-06-11 22:06:31 +00001473 else
1474 catch_sigstop = 1;
1475 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001477#ifdef __WALL
1478 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1479 if (errno == ECHILD) /* Already gone. */
1480 break;
1481 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001482 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001483 break;
1484 }
1485#endif /* __WALL */
1486 /* No __WALL here. */
1487 if (waitpid(tcp->pid, &status, 0) < 0) {
1488 if (errno != ECHILD) {
1489 perror("detach: waiting");
1490 break;
1491 }
1492#ifdef __WCLONE
1493 /* If no processes, try clones. */
1494 if (wait4(tcp->pid, &status, __WCLONE,
1495 NULL) < 0) {
1496 if (errno != ECHILD)
1497 perror("detach: waiting");
1498 break;
1499 }
1500#endif /* __WCLONE */
1501 }
1502#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001503 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001504#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505 if (!WIFSTOPPED(status)) {
1506 /* Au revoir, mon ami. */
1507 break;
1508 }
1509 if (WSTOPSIG(status) == SIGSTOP) {
1510 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001511 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 if (errno != ESRCH)
1513 perror("detach: ptrace(PTRACE_DETACH, ...)");
1514 /* I died trying. */
1515 }
1516 break;
1517 }
1518 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001519 WSTOPSIG(status) == SIGTRAP ?
1520 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521 if (errno != ESRCH)
1522 perror("detach: ptrace(PTRACE_CONT, ...)");
1523 break;
1524 }
1525 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001526#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527
1528#if defined(SUNOS4)
1529 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1530 if (sig && kill(tcp->pid, sig) < 0)
1531 perror("detach: kill");
1532 sig = 0;
1533 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1534 perror("detach: ptrace(PTRACE_DETACH, ...)");
1535#endif /* SUNOS4 */
1536
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001537#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001538 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001539#endif
1540
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 if (!qflag)
1542 fprintf(stderr, "Process %u detached\n", tcp->pid);
1543
1544 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001545
1546#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001547 if (zombie != NULL) {
1548 /* TCP no longer exists therefore you must not detach () it. */
1549 droptcb(zombie);
1550 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001551#endif
1552
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553 return error;
1554}
1555
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001556#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557
1558static void
1559reaper(sig)
1560int sig;
1561{
1562 int pid;
1563 int status;
1564
1565 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1566#if 0
1567 struct tcb *tcp;
1568
1569 tcp = pid2tcb(pid);
1570 if (tcp)
1571 droptcb(tcp);
1572#endif
1573 }
1574}
1575
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001576#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577
1578static void
1579cleanup()
1580{
1581 int i;
1582 struct tcb *tcp;
1583
Roland McGrathee9d4352002-12-18 04:16:10 +00001584 for (i = 0; i < tcbtabsize; i++) {
1585 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586 if (!(tcp->flags & TCB_INUSE))
1587 continue;
1588 if (debug)
1589 fprintf(stderr,
1590 "cleanup: looking at pid %u\n", tcp->pid);
1591 if (tcp_last &&
1592 (!outfname || followfork < 2 || tcp_last == tcp)) {
1593 tprintf(" <unfinished ...>\n");
1594 tcp_last = NULL;
1595 }
1596 if (tcp->flags & TCB_ATTACHED)
1597 detach(tcp, 0);
1598 else {
1599 kill(tcp->pid, SIGCONT);
1600 kill(tcp->pid, SIGTERM);
1601 }
1602 }
1603 if (cflag)
1604 call_summary(outf);
1605}
1606
1607static void
1608interrupt(sig)
1609int sig;
1610{
1611 interrupted = 1;
1612}
1613
1614#ifndef HAVE_STRERROR
1615
Roland McGrath6d2b3492002-12-30 00:51:30 +00001616#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617extern int sys_nerr;
1618extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001619#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620
1621const char *
1622strerror(errno)
1623int errno;
1624{
1625 static char buf[64];
1626
1627 if (errno < 1 || errno >= sys_nerr) {
1628 sprintf(buf, "Unknown error %d", errno);
1629 return buf;
1630 }
1631 return sys_errlist[errno];
1632}
1633
1634#endif /* HAVE_STERRROR */
1635
1636#ifndef HAVE_STRSIGNAL
1637
Roland McGrath8f474e02003-01-14 07:53:33 +00001638#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001639extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001641#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1642extern char *_sys_siglist[];
1643#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644
1645const char *
1646strsignal(sig)
1647int sig;
1648{
1649 static char buf[64];
1650
1651 if (sig < 1 || sig >= NSIG) {
1652 sprintf(buf, "Unknown signal %d", sig);
1653 return buf;
1654 }
1655#ifdef HAVE__SYS_SIGLIST
1656 return _sys_siglist[sig];
1657#else
1658 return sys_siglist[sig];
1659#endif
1660}
1661
1662#endif /* HAVE_STRSIGNAL */
1663
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001664#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665
1666static void
1667rebuild_pollv()
1668{
1669 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670
Roland McGrathee9d4352002-12-18 04:16:10 +00001671 if (pollv != NULL)
1672 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001673 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001674 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001675 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001676 exit(1);
1677 }
1678
Roland McGrathca16be82003-01-10 19:55:28 +00001679 for (i = j = 0; i < tcbtabsize; i++) {
1680 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 if (!(tcp->flags & TCB_INUSE))
1682 continue;
1683 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001684 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 j++;
1686 }
1687 if (j != nprocs) {
1688 fprintf(stderr, "strace: proc miscount\n");
1689 exit(1);
1690 }
1691}
1692
1693#ifndef HAVE_POLLABLE_PROCFS
1694
1695static void
1696proc_poll_open()
1697{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698 int i;
1699
1700 if (pipe(proc_poll_pipe) < 0) {
1701 perror("pipe");
1702 exit(1);
1703 }
1704 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001705 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706 exit(1);
1707 }
1708 }
1709}
1710
1711static int
1712proc_poll(pollv, nfds, timeout)
1713struct pollfd *pollv;
1714int nfds;
1715int timeout;
1716{
1717 int i;
1718 int n;
1719 struct proc_pollfd pollinfo;
1720
1721 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1722 return n;
1723 if (n != sizeof(struct proc_pollfd)) {
1724 fprintf(stderr, "panic: short read: %d\n", n);
1725 exit(1);
1726 }
1727 for (i = 0; i < nprocs; i++) {
1728 if (pollv[i].fd == pollinfo.fd)
1729 pollv[i].revents = pollinfo.revents;
1730 else
1731 pollv[i].revents = 0;
1732 }
1733 poller_pid = pollinfo.pid;
1734 return 1;
1735}
1736
1737static void
1738wakeup_handler(sig)
1739int sig;
1740{
1741}
1742
1743static void
1744proc_poller(pfd)
1745int pfd;
1746{
1747 struct proc_pollfd pollinfo;
1748 struct sigaction sa;
1749 sigset_t blocked_set, empty_set;
1750 int i;
1751 int n;
1752 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001753#ifdef FREEBSD
1754 struct procfs_status pfs;
1755#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756
1757 switch (fork()) {
1758 case -1:
1759 perror("fork");
1760 _exit(0);
1761 case 0:
1762 break;
1763 default:
1764 return;
1765 }
1766
1767 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1768 sa.sa_flags = 0;
1769 sigemptyset(&sa.sa_mask);
1770 sigaction(SIGHUP, &sa, NULL);
1771 sigaction(SIGINT, &sa, NULL);
1772 sigaction(SIGQUIT, &sa, NULL);
1773 sigaction(SIGPIPE, &sa, NULL);
1774 sigaction(SIGTERM, &sa, NULL);
1775 sa.sa_handler = wakeup_handler;
1776 sigaction(SIGUSR1, &sa, NULL);
1777 sigemptyset(&blocked_set);
1778 sigaddset(&blocked_set, SIGUSR1);
1779 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1780 sigemptyset(&empty_set);
1781
1782 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1783 perror("getrlimit(RLIMIT_NOFILE, ...)");
1784 _exit(0);
1785 }
1786 n = rl.rlim_cur;
1787 for (i = 0; i < n; i++) {
1788 if (i != pfd && i != proc_poll_pipe[1])
1789 close(i);
1790 }
1791
1792 pollinfo.fd = pfd;
1793 pollinfo.pid = getpid();
1794 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001795#ifndef FREEBSD
1796 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1797#else /* FREEBSD */
1798 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1799#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001800 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801 switch (errno) {
1802 case EINTR:
1803 continue;
1804 case EBADF:
1805 pollinfo.revents = POLLERR;
1806 break;
1807 case ENOENT:
1808 pollinfo.revents = POLLHUP;
1809 break;
1810 default:
1811 perror("proc_poller: PIOCWSTOP");
1812 }
1813 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1814 _exit(0);
1815 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001816 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1818 sigsuspend(&empty_set);
1819 }
1820}
1821
1822#endif /* !HAVE_POLLABLE_PROCFS */
1823
1824static int
1825choose_pfd()
1826{
1827 int i, j;
1828 struct tcb *tcp;
1829
1830 static int last;
1831
1832 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001833 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834 /*
1835 * The previous process is ready to run again. We'll
1836 * let it do so if it is currently in a syscall. This
1837 * heuristic improves the readability of the trace.
1838 */
1839 tcp = pfd2tcb(pollv[last].fd);
1840 if (tcp && (tcp->flags & TCB_INSYSCALL))
1841 return pollv[last].fd;
1842 }
1843
1844 for (i = 0; i < nprocs; i++) {
1845 /* Let competing children run round robin. */
1846 j = (i + last + 1) % nprocs;
1847 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1848 tcp = pfd2tcb(pollv[j].fd);
1849 if (!tcp) {
1850 fprintf(stderr, "strace: lost proc\n");
1851 exit(1);
1852 }
1853 droptcb(tcp);
1854 return -1;
1855 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001856 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 last = j;
1858 return pollv[j].fd;
1859 }
1860 }
1861 fprintf(stderr, "strace: nothing ready\n");
1862 exit(1);
1863}
1864
1865static int
1866trace()
1867{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001868#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001869 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001870#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871 struct tcb *tcp;
1872 int pfd;
1873 int what;
1874 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001875 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876
1877 for (;;) {
1878 if (interactive)
1879 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1880
1881 if (nprocs == 0)
1882 break;
1883
1884 switch (nprocs) {
1885 case 1:
1886#ifndef HAVE_POLLABLE_PROCFS
1887 if (proc_poll_pipe[0] == -1) {
1888#endif
1889 tcp = pid2tcb(0);
1890 if (!tcp)
1891 continue;
1892 pfd = tcp->pfd;
1893 if (pfd == -1)
1894 continue;
1895 break;
1896#ifndef HAVE_POLLABLE_PROCFS
1897 }
1898 /* fall through ... */
1899#endif /* !HAVE_POLLABLE_PROCFS */
1900 default:
1901#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001902#ifdef POLL_HACK
1903 /* On some systems (e.g. UnixWare) we get too much ugly
1904 "unfinished..." stuff when multiple proceses are in
1905 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001906
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001907 if (in_syscall) {
1908 struct pollfd pv;
1909 tcp = in_syscall;
1910 in_syscall = NULL;
1911 pv.fd = tcp->pfd;
1912 pv.events = POLLWANT;
1913 if ((what = poll (&pv, 1, 1)) < 0) {
1914 if (interrupted)
1915 return 0;
1916 continue;
1917 }
1918 else if (what == 1 && pv.revents & POLLWANT) {
1919 goto FOUND;
1920 }
1921 }
1922#endif
1923
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 if (poll(pollv, nprocs, INFTIM) < 0) {
1925 if (interrupted)
1926 return 0;
1927 continue;
1928 }
1929#else /* !HAVE_POLLABLE_PROCFS */
1930 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1931 if (interrupted)
1932 return 0;
1933 continue;
1934 }
1935#endif /* !HAVE_POLLABLE_PROCFS */
1936 pfd = choose_pfd();
1937 if (pfd == -1)
1938 continue;
1939 break;
1940 }
1941
1942 /* Look up `pfd' in our table. */
1943 if ((tcp = pfd2tcb(pfd)) == NULL) {
1944 fprintf(stderr, "unknown pfd: %u\n", pfd);
1945 exit(1);
1946 }
John Hughesb6643082002-05-23 11:02:22 +00001947#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001948 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001949#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 /* Get the status of the process. */
1951 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001952#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001953 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001954#else /* FREEBSD */
1955 /* Thanks to some scheduling mystery, the first poller
1956 sometimes waits for the already processed end of fork
1957 event. Doing a non blocking poll here solves the problem. */
1958 if (proc_poll_pipe[0] != -1)
1959 ioctl_result = IOCTL_STATUS (tcp);
1960 else
1961 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001962#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001963 ioctl_errno = errno;
1964#ifndef HAVE_POLLABLE_PROCFS
1965 if (proc_poll_pipe[0] != -1) {
1966 if (ioctl_result < 0)
1967 kill(poller_pid, SIGKILL);
1968 else
1969 kill(poller_pid, SIGUSR1);
1970 }
1971#endif /* !HAVE_POLLABLE_PROCFS */
1972 }
1973 if (interrupted)
1974 return 0;
1975
1976 if (interactive)
1977 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1978
1979 if (ioctl_result < 0) {
1980 /* Find out what happened if it failed. */
1981 switch (ioctl_errno) {
1982 case EINTR:
1983 case EBADF:
1984 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001985#ifdef FREEBSD
1986 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001987#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001988 case ENOENT:
1989 droptcb(tcp);
1990 continue;
1991 default:
1992 perror("PIOCWSTOP");
1993 exit(1);
1994 }
1995 }
1996
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001997#ifdef FREEBSD
1998 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1999 /* discard first event for a syscall we never entered */
2000 IOCTL (tcp->pfd, PIOCRUN, 0);
2001 continue;
2002 }
Roland McGrath553a6092002-12-16 20:40:39 +00002003#endif
2004
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002005 /* clear the just started flag */
2006 tcp->flags &= ~TCB_STARTUP;
2007
2008 /* set current output file */
2009 outf = tcp->outf;
2010
2011 if (cflag) {
2012 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002013#ifdef FREEBSD
2014 char buf[1024];
2015 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002017 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2018 buf[len] = '\0';
2019 sscanf(buf,
2020 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2021 &stime.tv_sec, &stime.tv_usec);
2022 } else
2023 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002024#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2026 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002027#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2029 tcp->stime = stime;
2030 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002031 what = tcp->status.PR_WHAT;
2032 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002033#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002035 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2036 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037 if (trace_syscall(tcp) < 0) {
2038 fprintf(stderr, "syscall trouble\n");
2039 exit(1);
2040 }
2041 }
2042 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002043#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002045#ifdef POLL_HACK
2046 in_syscall = tcp;
2047#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 case PR_SYSEXIT:
2049 if (trace_syscall(tcp) < 0) {
2050 fprintf(stderr, "syscall trouble\n");
2051 exit(1);
2052 }
2053 break;
2054 case PR_SIGNALLED:
2055 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2056 printleader(tcp);
2057 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002058 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002060#ifdef PR_INFO
2061 if (tcp->status.PR_INFO.si_signo == what) {
2062 printleader(tcp);
2063 tprintf(" siginfo=");
2064 printsiginfo(&tcp->status.PR_INFO, 1);
2065 printtrailer(tcp);
2066 }
2067#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068 }
2069 break;
2070 case PR_FAULTED:
2071 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2072 printleader(tcp);
2073 tprintf("=== FAULT %d ===", what);
2074 printtrailer(tcp);
2075 }
2076 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002077#ifdef FREEBSD
2078 case 0: /* handle case we polled for nothing */
2079 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002080#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002082 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083 exit(1);
2084 break;
2085 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002086 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002087#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002088 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002089#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002090 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002091#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 perror("PIOCRUN");
2093 exit(1);
2094 }
2095 }
2096 return 0;
2097}
2098
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002099#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002101#ifdef TCB_GROUP_EXITING
2102/* Handle an exit detach or death signal that is taking all the
2103 related clone threads with it. This is called in three circumstances:
2104 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2105 SIG == 0 Continuing TCP will perform an exit_group syscall.
2106 SIG == other Continuing TCP with SIG will kill the process.
2107*/
2108static int
2109handle_group_exit(struct tcb *tcp, int sig)
2110{
2111 /* We need to locate our records of all the clone threads
2112 related to TCP, either its children or siblings. */
2113 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2114 ? tcp->parent
2115 : tcp->nclone_detached > 0
2116 ? tcp : NULL);
2117
2118 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002119 if (leader != NULL && leader != tcp &&
2120 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002121 fprintf(stderr,
2122 "PANIC: handle_group_exit: %d leader %d\n",
2123 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002124 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002125#ifndef USE_PROCFS
2126 resume_from_tcp (tcp);
2127#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002128 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002129 }
2130 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002131 /* Mark that we are taking the process down. */
2132 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002133 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002134 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002135 if (leader != NULL && leader != tcp)
2136 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002137 }
2138 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2139 perror("strace: ptrace(PTRACE_CONT, ...)");
2140 cleanup();
2141 return -1;
2142 }
2143 else {
Roland McGrath05690952004-10-20 01:00:27 +00002144 if (leader != NULL)
2145 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002146 if (leader != NULL && leader != tcp)
2147 droptcb(tcp);
2148 /* The leader will report to us as parent now,
2149 and then we'll get to the SIG==-1 case. */
2150 return 0;
2151 }
2152 }
2153
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002154 return 0;
2155}
2156#endif
2157
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002158static int
2159trace()
2160{
2161 int pid;
2162 int wait_errno;
2163 int status;
2164 struct tcb *tcp;
2165#ifdef LINUX
2166 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002167#ifdef __WALL
2168 static int wait4_options = __WALL;
2169#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170#endif /* LINUX */
2171
2172 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002173 if (interrupted)
2174 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002175 if (interactive)
2176 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2177#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002178#ifdef __WALL
2179 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002180 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002181 /* this kernel does not support __WALL */
2182 wait4_options &= ~__WALL;
2183 errno = 0;
2184 pid = wait4(-1, &status, wait4_options,
2185 cflag ? &ru : NULL);
2186 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002187 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002188 /* most likely a "cloned" process */
2189 pid = wait4(-1, &status, __WCLONE,
2190 cflag ? &ru : NULL);
2191 if (pid == -1) {
2192 fprintf(stderr, "strace: clone wait4 "
2193 "failed: %s\n", strerror(errno));
2194 }
2195 }
2196#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002198#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199#endif /* LINUX */
2200#ifdef SUNOS4
2201 pid = wait(&status);
2202#endif /* SUNOS4 */
2203 wait_errno = errno;
2204 if (interactive)
2205 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2206
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207 if (pid == -1) {
2208 switch (wait_errno) {
2209 case EINTR:
2210 continue;
2211 case ECHILD:
2212 /*
2213 * We would like to verify this case
2214 * but sometimes a race in Solbourne's
2215 * version of SunOS sometimes reports
2216 * ECHILD before sending us SIGCHILD.
2217 */
2218#if 0
2219 if (nprocs == 0)
2220 return 0;
2221 fprintf(stderr, "strace: proc miscount\n");
2222 exit(1);
2223#endif
2224 return 0;
2225 default:
2226 errno = wait_errno;
2227 perror("strace: wait");
2228 return -1;
2229 }
2230 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002231 if (pid == popen_pid) {
2232 if (WIFEXITED(status) || WIFSIGNALED(status))
2233 popen_pid = -1;
2234 continue;
2235 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 if (debug)
2237 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2238
2239 /* Look up `pid' in our table. */
2240 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002241#ifdef LINUX
2242 if (followfork || followvfork) {
2243 /* This is needed to go with the CLONE_PTRACE
2244 changes in process.c/util.c: we might see
2245 the child's initial trap before we see the
2246 parent return from the clone syscall.
2247 Leave the child suspended until the parent
2248 returns from its system call. Only then
2249 will we have the association of parent and
2250 child so that we know how to do clearbpt
2251 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002252 if (nprocs == tcbtabsize &&
2253 expand_tcbtab())
2254 tcp = NULL;
2255 else
2256 tcp = alloctcb(pid);
2257 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002258 kill(pid, SIGKILL); /* XXX */
2259 return 0;
2260 }
2261 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002262 if (!qflag)
2263 fprintf(stderr, "\
2264Process %d attached (waiting for parent)\n",
2265 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002266 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002267 else
2268 /* This can happen if a clone call used
2269 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002270#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002271 {
2272 fprintf(stderr, "unknown pid: %u\n", pid);
2273 if (WIFSTOPPED(status))
2274 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2275 exit(1);
2276 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277 }
2278 /* set current output file */
2279 outf = tcp->outf;
2280 if (cflag) {
2281#ifdef LINUX
2282 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2283 tcp->stime = ru.ru_stime;
2284#endif /* !LINUX */
2285 }
2286
2287 if (tcp->flags & TCB_SUSPENDED) {
2288 /*
2289 * Apparently, doing any ptrace() call on a stopped
2290 * process, provokes the kernel to report the process
2291 * status again on a subsequent wait(), even if the
2292 * process has not been actually restarted.
2293 * Since we have inspected the arguments of suspended
2294 * processes we end up here testing for this case.
2295 */
2296 continue;
2297 }
2298 if (WIFSIGNALED(status)) {
2299 if (!cflag
2300 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2301 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002302 tprintf("+++ killed by %s %s+++",
2303 signame(WTERMSIG(status)),
2304#ifdef WCOREDUMP
2305 WCOREDUMP(status) ? "(core dumped) " :
2306#endif
2307 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 printtrailer(tcp);
2309 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002310#ifdef TCB_GROUP_EXITING
2311 handle_group_exit(tcp, -1);
2312#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002313 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002314#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002315 continue;
2316 }
2317 if (WIFEXITED(status)) {
2318 if (debug)
2319 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002320 if ((tcp->flags & TCB_ATTACHED)
2321#ifdef TCB_GROUP_EXITING
2322 && !(tcp->parent && (tcp->parent->flags &
2323 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002324 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002325#endif
2326 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002327 fprintf(stderr,
2328 "PANIC: attached pid %u exited\n",
2329 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002330 if (tcp == tcp_last) {
2331 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2332 == TCB_INSYSCALL)
2333 tprintf(" <unfinished ... exit status %d>\n",
2334 WEXITSTATUS(status));
2335 tcp_last = NULL;
2336 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002337#ifdef TCB_GROUP_EXITING
2338 handle_group_exit(tcp, -1);
2339#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002341#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002342 continue;
2343 }
2344 if (!WIFSTOPPED(status)) {
2345 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2346 droptcb(tcp);
2347 continue;
2348 }
2349 if (debug)
2350 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002351 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352
Roland McGrath02203312007-06-11 22:06:31 +00002353 /*
2354 * Interestingly, the process may stop
2355 * with STOPSIG equal to some other signal
2356 * than SIGSTOP if we happend to attach
2357 * just before the process takes a signal.
2358 */
2359 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002360 /*
2361 * This flag is there to keep us in sync.
2362 * Next time this process stops it should
2363 * really be entering a system call.
2364 */
2365 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002366 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002367 /*
2368 * One example is a breakpoint inherited from
2369 * parent through fork ().
2370 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002371 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2372 droptcb(tcp);
2373 cleanup();
2374 return -1;
2375 }
2376 }
2377 goto tracing;
2378 }
2379
2380 if (WSTOPSIG(status) != SIGTRAP) {
2381 if (WSTOPSIG(status) == SIGSTOP &&
2382 (tcp->flags & TCB_SIGTRAPPED)) {
2383 /*
2384 * Trapped attempt to block SIGTRAP
2385 * Hope we are back in control now.
2386 */
2387 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2388 if (ptrace(PTRACE_SYSCALL,
2389 pid, (char *) 1, 0) < 0) {
2390 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2391 cleanup();
2392 return -1;
2393 }
2394 continue;
2395 }
2396 if (!cflag
2397 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002398 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002399#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002400# define PSR_RI 41
2401 struct siginfo si;
2402 unsigned long psr;
2403
2404 upeek(pid, PT_CR_IPSR, &psr);
2405 upeek(pid, PT_CR_IIP, &pc);
2406
2407 pc += (psr >> PSR_RI) & 0x3;
2408 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2409 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002410#elif defined PTRACE_GETSIGINFO
2411 if (WSTOPSIG(status) == SIGSEGV ||
2412 WSTOPSIG(status) == SIGBUS) {
2413 siginfo_t si;
2414 if (ptrace(PTRACE_GETSIGINFO, pid,
2415 0, &si) == 0)
2416 addr = (unsigned long)
2417 si.si_addr;
2418 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002419#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002421 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002422 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002423 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 printtrailer(tcp);
2425 }
Roland McGrath05690952004-10-20 01:00:27 +00002426 if (((tcp->flags & TCB_ATTACHED) ||
2427 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002429#ifdef TCB_GROUP_EXITING
2430 handle_group_exit(tcp, WSTOPSIG(status));
2431#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002432 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002433#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 continue;
2435 }
2436 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2437 WSTOPSIG(status)) < 0) {
2438 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2439 cleanup();
2440 return -1;
2441 }
2442 tcp->flags &= ~TCB_SUSPENDED;
2443 continue;
2444 }
Roland McGrath02203312007-06-11 22:06:31 +00002445 /* we handled the STATUS, we are permitted to interrupt now. */
2446 if (interrupted)
2447 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002448 if (trace_syscall(tcp) < 0) {
2449 if (tcp->flags & TCB_ATTACHED)
2450 detach(tcp, 0);
2451 else {
2452 ptrace(PTRACE_KILL,
2453 tcp->pid, (char *) 1, SIGTERM);
2454 droptcb(tcp);
2455 }
2456 continue;
2457 }
2458 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002459#ifdef TCB_GROUP_EXITING
2460 if (tcp->flags & TCB_GROUP_EXITING) {
2461 if (handle_group_exit(tcp, 0) < 0)
2462 return -1;
2463 continue;
2464 }
2465#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002466 if (tcp->flags & TCB_ATTACHED)
2467 detach(tcp, 0);
2468 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2469 perror("strace: ptrace(PTRACE_CONT, ...)");
2470 cleanup();
2471 return -1;
2472 }
2473 continue;
2474 }
2475 if (tcp->flags & TCB_SUSPENDED) {
2476 if (!qflag)
2477 fprintf(stderr, "Process %u suspended\n", pid);
2478 continue;
2479 }
2480 tracing:
2481 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2482 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2483 cleanup();
2484 return -1;
2485 }
2486 }
2487 return 0;
2488}
2489
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002490#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002491
2492static int curcol;
2493
2494#ifdef __STDC__
2495#include <stdarg.h>
2496#define VA_START(a, b) va_start(a, b)
2497#else
2498#include <varargs.h>
2499#define VA_START(a, b) va_start(a)
2500#endif
2501
2502void
2503#ifdef __STDC__
2504tprintf(const char *fmt, ...)
2505#else
2506tprintf(fmt, va_alist)
2507char *fmt;
2508va_dcl
2509#endif
2510{
2511 va_list args;
2512
2513 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002514 if (outf) {
2515 int n = vfprintf(outf, fmt, args);
2516 if (n < 0 && outf != stderr)
2517 perror(outfname == NULL
2518 ? "<writing to pipe>" : outfname);
2519 else
2520 curcol += n;
2521 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002522 va_end(args);
2523 return;
2524}
2525
2526void
2527printleader(tcp)
2528struct tcb *tcp;
2529{
2530 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2531 tcp_last->flags |= TCB_REPRINT;
2532 tprintf(" <unfinished ...>\n");
2533 }
2534 curcol = 0;
2535 if ((followfork == 1 || pflag_seen > 1) && outfname)
2536 tprintf("%-5d ", tcp->pid);
2537 else if (nprocs > 1 && !outfname)
2538 tprintf("[pid %5u] ", tcp->pid);
2539 if (tflag) {
2540 char str[sizeof("HH:MM:SS")];
2541 struct timeval tv, dtv;
2542 static struct timeval otv;
2543
2544 gettimeofday(&tv, NULL);
2545 if (rflag) {
2546 if (otv.tv_sec == 0)
2547 otv = tv;
2548 tv_sub(&dtv, &tv, &otv);
2549 tprintf("%6ld.%06ld ",
2550 (long) dtv.tv_sec, (long) dtv.tv_usec);
2551 otv = tv;
2552 }
2553 else if (tflag > 2) {
2554 tprintf("%ld.%06ld ",
2555 (long) tv.tv_sec, (long) tv.tv_usec);
2556 }
2557 else {
2558 time_t local = tv.tv_sec;
2559 strftime(str, sizeof(str), "%T", localtime(&local));
2560 if (tflag > 1)
2561 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2562 else
2563 tprintf("%s ", str);
2564 }
2565 }
2566 if (iflag)
2567 printcall(tcp);
2568}
2569
2570void
2571tabto(col)
2572int col;
2573{
2574 if (curcol < col)
2575 tprintf("%*s", col - curcol, "");
2576}
2577
2578void
2579printtrailer(tcp)
2580struct tcb *tcp;
2581{
2582 tprintf("\n");
2583 tcp_last = NULL;
2584}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002585
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002586#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002587
2588int mp_ioctl (int fd, int cmd, void *arg, int size) {
2589
2590 struct iovec iov[2];
2591 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002592
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002593 iov[0].iov_base = &cmd;
2594 iov[0].iov_len = sizeof cmd;
2595 if (arg) {
2596 ++n;
2597 iov[1].iov_base = arg;
2598 iov[1].iov_len = size;
2599 }
Roland McGrath553a6092002-12-16 20:40:39 +00002600
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002601 return writev (fd, iov, n);
2602}
2603
2604#endif