blob: 0cbe3228c9e40745898b66754b05936e35179387 [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
Roland McGrath41c48222008-07-18 00:25:10 +000081int debug = 0, followfork = 0;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000082int 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;
Roland McGrath41c48222008-07-18 00:25:10 +0000662 case 'F':
663 /* Obsoleted, acts as `-f'. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000664 case 'f':
665 followfork++;
666 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667 case 'h':
668 usage(stdout, 0);
669 break;
670 case 'i':
671 iflag++;
672 break;
673 case 'q':
674 qflag++;
675 break;
676 case 'r':
677 rflag++;
678 tflag++;
679 break;
680 case 't':
681 tflag++;
682 break;
683 case 'T':
684 dtime++;
685 break;
686 case 'x':
687 xflag++;
688 break;
689 case 'v':
690 qualify("abbrev=none");
691 break;
692 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000693 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694 exit(0);
695 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000696 case 'z':
697 not_failing_only = 1;
698 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699 case 'a':
700 acolumn = atoi(optarg);
701 break;
702 case 'e':
703 qualify(optarg);
704 break;
705 case 'o':
706 outfname = strdup(optarg);
707 break;
708 case 'O':
709 set_overhead(atoi(optarg));
710 break;
711 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000712 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713 fprintf(stderr, "%s: Invalid process id: %s\n",
714 progname, optarg);
715 break;
716 }
717 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000718 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 break;
720 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000721 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000722 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 progname);
724 exit(1);
725 }
726 tcp->flags |= TCB_ATTACHED;
727 pflag_seen++;
728 break;
729 case 's':
730 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000731 if (max_strlen < 0) {
732 fprintf(stderr,
733 "%s: invalid -s argument: %s\n",
734 progname, optarg);
735 exit(1);
736 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737 break;
738 case 'S':
739 set_sortby(optarg);
740 break;
741 case 'u':
742 username = strdup(optarg);
743 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000744 case 'E':
745 if (putenv(optarg) < 0) {
746 fprintf(stderr, "%s: out of memory\n",
747 progname);
748 exit(1);
749 }
750 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751 default:
752 usage(stderr, 1);
753 break;
754 }
755 }
756
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000757 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000758 usage(stderr, 1);
759
Roland McGrathcb9def62006-04-25 07:48:03 +0000760 if (followfork > 1 && cflag) {
761 fprintf(stderr,
762 "%s: -c and -ff are mutually exclusive options\n",
763 progname);
764 exit(1);
765 }
766
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 /* See if they want to run as another user. */
768 if (username != NULL) {
769 struct passwd *pent;
770
771 if (getuid() != 0 || geteuid() != 0) {
772 fprintf(stderr,
773 "%s: you must be root to use the -u option\n",
774 progname);
775 exit(1);
776 }
777 if ((pent = getpwnam(username)) == NULL) {
778 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000779 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000780 exit(1);
781 }
782 run_uid = pent->pw_uid;
783 run_gid = pent->pw_gid;
784 }
785 else {
786 run_uid = getuid();
787 run_gid = getgid();
788 }
789
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000790 /* Check if they want to redirect the output. */
791 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000792 /* See if they want to pipe the output. */
793 if (outfname[0] == '|' || outfname[0] == '!') {
794 /*
795 * We can't do the <outfname>.PID funny business
796 * when using popen, so prohibit it.
797 */
798 if (followfork > 1) {
799 fprintf(stderr, "\
800%s: piping the output and -ff are mutually exclusive options\n",
801 progname);
802 exit(1);
803 }
804
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000805 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000806 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000807 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000808 else if (followfork <= 1 &&
809 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000810 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 }
812
Roland McGrath37b9a662003-11-07 02:26:54 +0000813 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000815 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000817 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000818 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000819 /* Valid states here:
820 optind < argc pflag_seen outfname interactive
821 1 0 0 1
822 0 1 0 1
823 1 0 1 0
824 0 1 1 1
825 */
826
827 /* STARTUP_CHILD must be called before the signal handlers get
828 installed below as they are inherited into the spawned process.
829 Also we do not need to be protected by them as during interruption
830 in the STARTUP_CHILD mode we kill the spawned process anyway. */
831 if (!pflag_seen)
832 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000833
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834 sigemptyset(&empty_set);
835 sigemptyset(&blocked_set);
836 sa.sa_handler = SIG_IGN;
837 sigemptyset(&sa.sa_mask);
838 sa.sa_flags = 0;
839 sigaction(SIGTTOU, &sa, NULL);
840 sigaction(SIGTTIN, &sa, NULL);
841 if (interactive) {
842 sigaddset(&blocked_set, SIGHUP);
843 sigaddset(&blocked_set, SIGINT);
844 sigaddset(&blocked_set, SIGQUIT);
845 sigaddset(&blocked_set, SIGPIPE);
846 sigaddset(&blocked_set, SIGTERM);
847 sa.sa_handler = interrupt;
848#ifdef SUNOS4
849 /* POSIX signals on sunos4.1 are a little broken. */
850 sa.sa_flags = SA_INTERRUPT;
851#endif /* SUNOS4 */
852 }
853 sigaction(SIGHUP, &sa, NULL);
854 sigaction(SIGINT, &sa, NULL);
855 sigaction(SIGQUIT, &sa, NULL);
856 sigaction(SIGPIPE, &sa, NULL);
857 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000858#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000859 sa.sa_handler = reaper;
860 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000861#else
862 /* Make sure SIGCHLD has the default action so that waitpid
863 definitely works without losing track of children. The user
864 should not have given us a bogus state to inherit, but he might
865 have. Arguably we should detect SIG_IGN here and pass it on
866 to children, but probably noone really needs that. */
867 sa.sa_handler = SIG_DFL;
868 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000869#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870
Roland McGrath02203312007-06-11 22:06:31 +0000871 if (pflag_seen)
872 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000873
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000874 if (trace() < 0)
875 exit(1);
876 cleanup();
877 exit(0);
878}
879
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000880int
881expand_tcbtab()
882{
883 /* Allocate some more TCBs and expand the table.
884 We don't want to relocate the TCBs because our
885 callers have pointers and it would be a pain.
886 So tcbtab is a table of pointers. Since we never
887 free the TCBs, we allocate a single chunk of many. */
888 struct tcb **newtab = (struct tcb **)
889 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
890 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
891 sizeof *newtcbs);
892 int i;
893 if (newtab == NULL || newtcbs == NULL) {
894 if (newtab != NULL)
895 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000896 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
897 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000898 return 1;
899 }
900 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
901 newtab[i] = &newtcbs[i - tcbtabsize];
902 tcbtabsize *= 2;
903 tcbtab = newtab;
904
905 return 0;
906}
907
908
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000910alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911{
912 int i;
913 struct tcb *tcp;
914
Roland McGrathee9d4352002-12-18 04:16:10 +0000915 for (i = 0; i < tcbtabsize; i++) {
916 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 if ((tcp->flags & TCB_INUSE) == 0) {
918 tcp->pid = pid;
919 tcp->parent = NULL;
920 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000921 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000922#ifdef TCB_CLONE_THREAD
923 tcp->nclone_threads = tcp->nclone_detached = 0;
924 tcp->nclone_waiting = 0;
925#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000926 tcp->flags = TCB_INUSE | TCB_STARTUP;
927 tcp->outf = outf; /* Initialise to current out file */
928 tcp->stime.tv_sec = 0;
929 tcp->stime.tv_usec = 0;
930 tcp->pfd = -1;
931 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000932 if (command_options_parsed)
933 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934 return tcp;
935 }
936 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000937 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938 return NULL;
939}
940
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000941#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942int
943proc_open(tcp, attaching)
944struct tcb *tcp;
945int attaching;
946{
947 char proc[32];
948 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000949#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000950 int i;
951 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952 sigset_t signals;
953 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000954#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955#ifndef HAVE_POLLABLE_PROCFS
956 static int last_pfd;
957#endif
958
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000959#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000960 /* Open the process pseudo-files in /proc. */
961 sprintf(proc, "/proc/%d/ctl", tcp->pid);
962 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 perror("strace: open(\"/proc/...\", ...)");
964 return -1;
965 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000966 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 return -1;
968 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000969 sprintf(proc, "/proc/%d/status", tcp->pid);
970 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
971 perror("strace: open(\"/proc/...\", ...)");
972 return -1;
973 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000974 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000975 return -1;
976 }
977 sprintf(proc, "/proc/%d/as", tcp->pid);
978 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
979 perror("strace: open(\"/proc/...\", ...)");
980 return -1;
981 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000982 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000983 return -1;
984 }
985#else
986 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000987#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000988 sprintf(proc, "/proc/%d", tcp->pid);
989 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000990#else /* FREEBSD */
991 sprintf(proc, "/proc/%d/mem", tcp->pid);
992 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
993#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000994 perror("strace: open(\"/proc/...\", ...)");
995 return -1;
996 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000997 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000998 return -1;
999 }
1000#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001001#ifdef FREEBSD
1002 sprintf(proc, "/proc/%d/regs", tcp->pid);
1003 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1004 perror("strace: open(\"/proc/.../regs\", ...)");
1005 return -1;
1006 }
1007 if (cflag) {
1008 sprintf(proc, "/proc/%d/status", tcp->pid);
1009 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1010 perror("strace: open(\"/proc/.../status\", ...)");
1011 return -1;
1012 }
1013 } else
1014 tcp->pfd_status = -1;
1015#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001016 rebuild_pollv();
1017 if (!attaching) {
1018 /*
1019 * Wait for the child to pause. Because of a race
1020 * condition we have to poll for the event.
1021 */
1022 for (;;) {
1023 if (IOCTL_STATUS (tcp) < 0) {
1024 perror("strace: PIOCSTATUS");
1025 return -1;
1026 }
1027 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001028 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001029 }
1030 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001031#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001032 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001033 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001034 perror("strace: PIOCSTOP");
1035 return -1;
1036 }
Roland McGrath553a6092002-12-16 20:40:39 +00001037#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038#ifdef PIOCSET
1039 /* Set Run-on-Last-Close. */
1040 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001041 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 perror("PIOCSET PR_RLC");
1043 return -1;
1044 }
1045 /* Set or Reset Inherit-on-Fork. */
1046 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001047 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 perror("PIOC{SET,RESET} PR_FORK");
1049 return -1;
1050 }
1051#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001052#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1054 perror("PIOCSRLC");
1055 return -1;
1056 }
1057 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1058 perror("PIOC{S,R}FORK");
1059 return -1;
1060 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001061#else /* FREEBSD */
1062 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1063 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1064 perror("PIOCGFL");
1065 return -1;
1066 }
1067 arg &= ~PF_LINGER;
1068 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1069 perror("PIOCSFL");
1070 return -1;
1071 }
1072#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001074#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001075 /* Enable all syscall entries we care about. */
1076 premptyset(&syscalls);
1077 for (i = 1; i < MAX_QUALS; ++i) {
1078 if (i > (sizeof syscalls) * CHAR_BIT) break;
1079 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1080 }
1081 praddset (&syscalls, SYS_execve);
1082 if (followfork) {
1083 praddset (&syscalls, SYS_fork);
1084#ifdef SYS_forkall
1085 praddset (&syscalls, SYS_forkall);
1086#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001087#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001088 praddset (&syscalls, SYS_fork1);
1089#endif
1090#ifdef SYS_rfork1
1091 praddset (&syscalls, SYS_rfork1);
1092#endif
1093#ifdef SYS_rforkall
1094 praddset (&syscalls, SYS_rforkall);
1095#endif
1096 }
1097 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098 perror("PIOCSENTRY");
1099 return -1;
1100 }
John Hughes19e49982001-10-19 08:59:12 +00001101 /* Enable the syscall exits. */
1102 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103 perror("PIOSEXIT");
1104 return -1;
1105 }
John Hughes19e49982001-10-19 08:59:12 +00001106 /* Enable signals we care about. */
1107 premptyset(&signals);
1108 for (i = 1; i < MAX_QUALS; ++i) {
1109 if (i > (sizeof signals) * CHAR_BIT) break;
1110 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1111 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001112 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 perror("PIOCSTRACE");
1114 return -1;
1115 }
John Hughes19e49982001-10-19 08:59:12 +00001116 /* Enable faults we care about */
1117 premptyset(&faults);
1118 for (i = 1; i < MAX_QUALS; ++i) {
1119 if (i > (sizeof faults) * CHAR_BIT) break;
1120 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1121 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001122 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 perror("PIOCSFAULT");
1124 return -1;
1125 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001126#else /* FREEBSD */
1127 /* set events flags. */
1128 arg = S_SIG | S_SCE | S_SCX ;
1129 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1130 perror("PIOCBIS");
1131 return -1;
1132 }
1133#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134 if (!attaching) {
1135#ifdef MIPS
1136 /*
1137 * The SGI PRSABORT doesn't work for pause() so
1138 * we send it a caught signal to wake it up.
1139 */
1140 kill(tcp->pid, SIGINT);
1141#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001142#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001144 arg = PRSABORT;
1145 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 perror("PIOCRUN");
1147 return -1;
1148 }
Roland McGrath553a6092002-12-16 20:40:39 +00001149#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001150#endif /* !MIPS*/
1151#ifdef FREEBSD
1152 /* wake up the child if it received the SIGSTOP */
1153 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001154#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 for (;;) {
1156 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001157 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 perror("PIOCWSTOP");
1159 return -1;
1160 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001161 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001162 tcp->flags &= ~TCB_INSYSCALL;
1163 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001164 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 break;
1166 }
1167 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001168#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001169 arg = 0;
1170 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001171#else /* FREEBSD */
1172 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001173#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 perror("PIOCRUN");
1175 return -1;
1176 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001177#ifdef FREEBSD
1178 /* handle the case where we "opened" the child before
1179 it did the kill -STOP */
1180 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1181 tcp->status.PR_WHAT == SIGSTOP)
1182 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001183#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001185#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001187#else /* FREEBSD */
1188 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001189 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001190 /* We are attaching to an already running process.
1191 * Try to figure out the state of the process in syscalls,
1192 * to handle the first event well.
1193 * This is done by having a look at the "wchan" property of the
1194 * process, which tells where it is stopped (if it is). */
1195 FILE * status;
1196 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001197
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001198 sprintf(proc, "/proc/%d/status", tcp->pid);
1199 status = fopen(proc, "r");
1200 if (status &&
1201 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1202 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1203 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1204 strcmp(wchan, "stopevent")) {
1205 /* The process is asleep in the middle of a syscall.
1206 Fake the syscall entry event */
1207 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1208 tcp->status.PR_WHY = PR_SYSENTRY;
1209 trace_syscall(tcp);
1210 }
1211 if (status)
1212 fclose(status);
1213 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001214 }
1215#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216#ifndef HAVE_POLLABLE_PROCFS
1217 if (proc_poll_pipe[0] != -1)
1218 proc_poller(tcp->pfd);
1219 else if (nprocs > 1) {
1220 proc_poll_open();
1221 proc_poller(last_pfd);
1222 proc_poller(tcp->pfd);
1223 }
1224 last_pfd = tcp->pfd;
1225#endif /* !HAVE_POLLABLE_PROCFS */
1226 return 0;
1227}
1228
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001229#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001231struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232pid2tcb(pid)
1233int pid;
1234{
1235 int i;
1236 struct tcb *tcp;
1237
Roland McGrathee9d4352002-12-18 04:16:10 +00001238 for (i = 0; i < tcbtabsize; i++) {
1239 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001240 if (pid && tcp->pid != pid)
1241 continue;
1242 if (tcp->flags & TCB_INUSE)
1243 return tcp;
1244 }
1245 return NULL;
1246}
1247
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001248#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249
1250static struct tcb *
1251pfd2tcb(pfd)
1252int pfd;
1253{
1254 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255
Roland McGrathca16be82003-01-10 19:55:28 +00001256 for (i = 0; i < tcbtabsize; i++) {
1257 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001258 if (tcp->pfd != pfd)
1259 continue;
1260 if (tcp->flags & TCB_INUSE)
1261 return tcp;
1262 }
1263 return NULL;
1264}
1265
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001266#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267
1268void
1269droptcb(tcp)
1270struct tcb *tcp;
1271{
1272 if (tcp->pid == 0)
1273 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001274#ifdef TCB_CLONE_THREAD
1275 if (tcp->nclone_threads > 0) {
1276 /* There are other threads left in this process, but this
1277 is the one whose PID represents the whole process.
1278 We need to keep this record around as a zombie until
1279 all the threads die. */
1280 tcp->flags |= TCB_EXITING;
1281 return;
1282 }
1283#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284 nprocs--;
1285 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001286
Roland McGrathe29341c2003-01-10 20:14:20 +00001287 if (tcp->parent != NULL) {
1288 tcp->parent->nchildren--;
1289#ifdef TCB_CLONE_THREAD
1290 if (tcp->flags & TCB_CLONE_DETACHED)
1291 tcp->parent->nclone_detached--;
1292 if (tcp->flags & TCB_CLONE_THREAD)
1293 tcp->parent->nclone_threads--;
1294#endif
Roland McGrath09623452003-05-23 02:27:13 +00001295#ifdef TCB_CLONE_DETACHED
1296 if (!(tcp->flags & TCB_CLONE_DETACHED))
1297#endif
1298 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001299#ifdef LINUX
1300 /* Update `tcp->parent->parent->nchildren' and the other fields
1301 like NCLONE_DETACHED, only for zombie group leader that has
1302 already reported and been short-circuited at the top of this
1303 function. The same condition as at the top of DETACH. */
1304 if ((tcp->flags & TCB_CLONE_THREAD) &&
1305 tcp->parent->nclone_threads == 0 &&
1306 (tcp->parent->flags & TCB_EXITING))
1307 droptcb(tcp->parent);
1308#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001309 tcp->parent = NULL;
1310 }
1311
1312 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 if (tcp->pfd != -1) {
1314 close(tcp->pfd);
1315 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001316#ifdef FREEBSD
1317 if (tcp->pfd_reg != -1) {
1318 close(tcp->pfd_reg);
1319 tcp->pfd_reg = -1;
1320 }
1321 if (tcp->pfd_status != -1) {
1322 close(tcp->pfd_status);
1323 tcp->pfd_status = -1;
1324 }
Roland McGrath553a6092002-12-16 20:40:39 +00001325#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001326#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001327 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328#endif
1329 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001330
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001331 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001333
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334 tcp->outf = 0;
1335}
1336
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001338
1339static int
1340resume(tcp)
1341struct tcb *tcp;
1342{
1343 if (tcp == NULL)
1344 return -1;
1345
1346 if (!(tcp->flags & TCB_SUSPENDED)) {
1347 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1348 return -1;
1349 }
1350 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001351#ifdef TCB_CLONE_THREAD
1352 if (tcp->flags & TCB_CLONE_THREAD)
1353 tcp->parent->nclone_waiting--;
1354#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001355
1356 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1357 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1358 return -1;
1359 }
1360
1361 if (!qflag)
1362 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1363 return 0;
1364}
1365
Roland McGrath1bfd3102007-08-03 10:02:00 +00001366static int
1367resume_from_tcp (struct tcb *tcp)
1368{
1369 int error = 0;
1370 int resumed = 0;
1371
1372 /* XXX This won't always be quite right (but it never was).
1373 A waiter with argument 0 or < -1 is waiting for any pid in
1374 a particular pgrp, which this child might or might not be
1375 in. The waiter will only wake up if it's argument is -1
1376 or if it's waiting for tcp->pid's pgrp. It makes a
1377 difference to wake up a waiter when there might be more
1378 traced children, because it could get a false ECHILD
1379 error. OTOH, if this was the last child in the pgrp, then
1380 it ought to wake up and get ECHILD. We would have to
1381 search the system for all pid's in the pgrp to be sure.
1382
1383 && (t->waitpid == -1 ||
1384 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1385 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1386 */
1387
1388 if (tcp->parent &&
1389 (tcp->parent->flags & TCB_SUSPENDED) &&
1390 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1391 error = resume(tcp->parent);
1392 ++resumed;
1393 }
1394#ifdef TCB_CLONE_THREAD
1395 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1396 /* Some other threads of our parent are waiting too. */
1397 unsigned int i;
1398
1399 /* Resume all the threads that were waiting for this PID. */
1400 for (i = 0; i < tcbtabsize; i++) {
1401 struct tcb *t = tcbtab[i];
1402 if (t->parent == tcp->parent && t != tcp
1403 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1404 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1405 && t->waitpid == tcp->pid) {
1406 error |= resume (t);
1407 ++resumed;
1408 }
1409 }
1410 if (resumed == 0)
1411 /* Noone was waiting for this PID in particular,
1412 so now we might need to resume some wildcarders. */
1413 for (i = 0; i < tcbtabsize; i++) {
1414 struct tcb *t = tcbtab[i];
1415 if (t->parent == tcp->parent && t != tcp
1416 && ((t->flags
1417 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1418 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1419 && t->waitpid <= 0
1420 ) {
1421 error |= resume (t);
1422 break;
1423 }
1424 }
1425 }
1426
1427 return error;
1428}
1429#endif
1430
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001431#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432
Roland McGrath0a463882007-07-05 18:43:16 +00001433/* detach traced process; continue with sig
1434 Never call DETACH twice on the same process as both unattached and
1435 attached-unstopped processes give the same ESRCH. For unattached process we
1436 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437
1438static int
1439detach(tcp, sig)
1440struct tcb *tcp;
1441int sig;
1442{
1443 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001444#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001445 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001446 struct tcb *zombie = NULL;
1447
1448 /* If the group leader is lingering only because of this other
1449 thread now dying, then detach the leader as well. */
1450 if ((tcp->flags & TCB_CLONE_THREAD) &&
1451 tcp->parent->nclone_threads == 1 &&
1452 (tcp->parent->flags & TCB_EXITING))
1453 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001454#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455
1456 if (tcp->flags & TCB_BPTSET)
1457 sig = SIGKILL;
1458
1459#ifdef LINUX
1460 /*
1461 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001462 * before detaching. Arghh. We go through hoops
1463 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001465#if defined(SPARC)
1466#undef PTRACE_DETACH
1467#define PTRACE_DETACH PTRACE_SUNDETACH
1468#endif
Roland McGrath02203312007-06-11 22:06:31 +00001469 /*
1470 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1471 * expected SIGSTOP. We must catch exactly one as otherwise the
1472 * detached process would be left stopped (process state T).
1473 */
1474 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1476 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001477 }
1478 else if (errno != ESRCH) {
1479 /* Shouldn't happen. */
1480 perror("detach: ptrace(PTRACE_DETACH, ...)");
1481 }
Roland McGrath134813a2007-06-02 00:07:33 +00001482 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1483 : tcp->pid),
1484 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001485 if (errno != ESRCH)
1486 perror("detach: checking sanity");
1487 }
Roland McGrath02203312007-06-11 22:06:31 +00001488 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1489 ? tcp->parent->pid : tcp->pid),
1490 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001491 if (errno != ESRCH)
1492 perror("detach: stopping child");
1493 }
Roland McGrath02203312007-06-11 22:06:31 +00001494 else
1495 catch_sigstop = 1;
1496 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001497 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001498#ifdef __WALL
1499 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1500 if (errno == ECHILD) /* Already gone. */
1501 break;
1502 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001503 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001504 break;
1505 }
1506#endif /* __WALL */
1507 /* No __WALL here. */
1508 if (waitpid(tcp->pid, &status, 0) < 0) {
1509 if (errno != ECHILD) {
1510 perror("detach: waiting");
1511 break;
1512 }
1513#ifdef __WCLONE
1514 /* If no processes, try clones. */
1515 if (wait4(tcp->pid, &status, __WCLONE,
1516 NULL) < 0) {
1517 if (errno != ECHILD)
1518 perror("detach: waiting");
1519 break;
1520 }
1521#endif /* __WCLONE */
1522 }
1523#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001524 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001525#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526 if (!WIFSTOPPED(status)) {
1527 /* Au revoir, mon ami. */
1528 break;
1529 }
1530 if (WSTOPSIG(status) == SIGSTOP) {
1531 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001532 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 if (errno != ESRCH)
1534 perror("detach: ptrace(PTRACE_DETACH, ...)");
1535 /* I died trying. */
1536 }
1537 break;
1538 }
1539 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001540 WSTOPSIG(status) == SIGTRAP ?
1541 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542 if (errno != ESRCH)
1543 perror("detach: ptrace(PTRACE_CONT, ...)");
1544 break;
1545 }
1546 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001547#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001548
1549#if defined(SUNOS4)
1550 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1551 if (sig && kill(tcp->pid, sig) < 0)
1552 perror("detach: kill");
1553 sig = 0;
1554 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1555 perror("detach: ptrace(PTRACE_DETACH, ...)");
1556#endif /* SUNOS4 */
1557
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001558#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001559 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001560#endif
1561
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 if (!qflag)
1563 fprintf(stderr, "Process %u detached\n", tcp->pid);
1564
1565 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001566
1567#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001568 if (zombie != NULL) {
1569 /* TCP no longer exists therefore you must not detach () it. */
1570 droptcb(zombie);
1571 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001572#endif
1573
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 return error;
1575}
1576
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001577#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578
1579static void
1580reaper(sig)
1581int sig;
1582{
1583 int pid;
1584 int status;
1585
1586 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1587#if 0
1588 struct tcb *tcp;
1589
1590 tcp = pid2tcb(pid);
1591 if (tcp)
1592 droptcb(tcp);
1593#endif
1594 }
1595}
1596
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001597#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598
1599static void
1600cleanup()
1601{
1602 int i;
1603 struct tcb *tcp;
1604
Roland McGrathee9d4352002-12-18 04:16:10 +00001605 for (i = 0; i < tcbtabsize; i++) {
1606 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607 if (!(tcp->flags & TCB_INUSE))
1608 continue;
1609 if (debug)
1610 fprintf(stderr,
1611 "cleanup: looking at pid %u\n", tcp->pid);
1612 if (tcp_last &&
1613 (!outfname || followfork < 2 || tcp_last == tcp)) {
1614 tprintf(" <unfinished ...>\n");
1615 tcp_last = NULL;
1616 }
1617 if (tcp->flags & TCB_ATTACHED)
1618 detach(tcp, 0);
1619 else {
1620 kill(tcp->pid, SIGCONT);
1621 kill(tcp->pid, SIGTERM);
1622 }
1623 }
1624 if (cflag)
1625 call_summary(outf);
1626}
1627
1628static void
1629interrupt(sig)
1630int sig;
1631{
1632 interrupted = 1;
1633}
1634
1635#ifndef HAVE_STRERROR
1636
Roland McGrath6d2b3492002-12-30 00:51:30 +00001637#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638extern int sys_nerr;
1639extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001640#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641
1642const char *
1643strerror(errno)
1644int errno;
1645{
1646 static char buf[64];
1647
1648 if (errno < 1 || errno >= sys_nerr) {
1649 sprintf(buf, "Unknown error %d", errno);
1650 return buf;
1651 }
1652 return sys_errlist[errno];
1653}
1654
1655#endif /* HAVE_STERRROR */
1656
1657#ifndef HAVE_STRSIGNAL
1658
Roland McGrath8f474e02003-01-14 07:53:33 +00001659#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001660extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001662#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1663extern char *_sys_siglist[];
1664#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665
1666const char *
1667strsignal(sig)
1668int sig;
1669{
1670 static char buf[64];
1671
1672 if (sig < 1 || sig >= NSIG) {
1673 sprintf(buf, "Unknown signal %d", sig);
1674 return buf;
1675 }
1676#ifdef HAVE__SYS_SIGLIST
1677 return _sys_siglist[sig];
1678#else
1679 return sys_siglist[sig];
1680#endif
1681}
1682
1683#endif /* HAVE_STRSIGNAL */
1684
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001685#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686
1687static void
1688rebuild_pollv()
1689{
1690 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691
Roland McGrathee9d4352002-12-18 04:16:10 +00001692 if (pollv != NULL)
1693 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001694 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001695 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001696 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001697 exit(1);
1698 }
1699
Roland McGrathca16be82003-01-10 19:55:28 +00001700 for (i = j = 0; i < tcbtabsize; i++) {
1701 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 if (!(tcp->flags & TCB_INUSE))
1703 continue;
1704 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001705 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706 j++;
1707 }
1708 if (j != nprocs) {
1709 fprintf(stderr, "strace: proc miscount\n");
1710 exit(1);
1711 }
1712}
1713
1714#ifndef HAVE_POLLABLE_PROCFS
1715
1716static void
1717proc_poll_open()
1718{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719 int i;
1720
1721 if (pipe(proc_poll_pipe) < 0) {
1722 perror("pipe");
1723 exit(1);
1724 }
1725 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001726 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727 exit(1);
1728 }
1729 }
1730}
1731
1732static int
1733proc_poll(pollv, nfds, timeout)
1734struct pollfd *pollv;
1735int nfds;
1736int timeout;
1737{
1738 int i;
1739 int n;
1740 struct proc_pollfd pollinfo;
1741
1742 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1743 return n;
1744 if (n != sizeof(struct proc_pollfd)) {
1745 fprintf(stderr, "panic: short read: %d\n", n);
1746 exit(1);
1747 }
1748 for (i = 0; i < nprocs; i++) {
1749 if (pollv[i].fd == pollinfo.fd)
1750 pollv[i].revents = pollinfo.revents;
1751 else
1752 pollv[i].revents = 0;
1753 }
1754 poller_pid = pollinfo.pid;
1755 return 1;
1756}
1757
1758static void
1759wakeup_handler(sig)
1760int sig;
1761{
1762}
1763
1764static void
1765proc_poller(pfd)
1766int pfd;
1767{
1768 struct proc_pollfd pollinfo;
1769 struct sigaction sa;
1770 sigset_t blocked_set, empty_set;
1771 int i;
1772 int n;
1773 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001774#ifdef FREEBSD
1775 struct procfs_status pfs;
1776#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777
1778 switch (fork()) {
1779 case -1:
1780 perror("fork");
1781 _exit(0);
1782 case 0:
1783 break;
1784 default:
1785 return;
1786 }
1787
1788 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1789 sa.sa_flags = 0;
1790 sigemptyset(&sa.sa_mask);
1791 sigaction(SIGHUP, &sa, NULL);
1792 sigaction(SIGINT, &sa, NULL);
1793 sigaction(SIGQUIT, &sa, NULL);
1794 sigaction(SIGPIPE, &sa, NULL);
1795 sigaction(SIGTERM, &sa, NULL);
1796 sa.sa_handler = wakeup_handler;
1797 sigaction(SIGUSR1, &sa, NULL);
1798 sigemptyset(&blocked_set);
1799 sigaddset(&blocked_set, SIGUSR1);
1800 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1801 sigemptyset(&empty_set);
1802
1803 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1804 perror("getrlimit(RLIMIT_NOFILE, ...)");
1805 _exit(0);
1806 }
1807 n = rl.rlim_cur;
1808 for (i = 0; i < n; i++) {
1809 if (i != pfd && i != proc_poll_pipe[1])
1810 close(i);
1811 }
1812
1813 pollinfo.fd = pfd;
1814 pollinfo.pid = getpid();
1815 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001816#ifndef FREEBSD
1817 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1818#else /* FREEBSD */
1819 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1820#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001821 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822 switch (errno) {
1823 case EINTR:
1824 continue;
1825 case EBADF:
1826 pollinfo.revents = POLLERR;
1827 break;
1828 case ENOENT:
1829 pollinfo.revents = POLLHUP;
1830 break;
1831 default:
1832 perror("proc_poller: PIOCWSTOP");
1833 }
1834 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1835 _exit(0);
1836 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001837 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1839 sigsuspend(&empty_set);
1840 }
1841}
1842
1843#endif /* !HAVE_POLLABLE_PROCFS */
1844
1845static int
1846choose_pfd()
1847{
1848 int i, j;
1849 struct tcb *tcp;
1850
1851 static int last;
1852
1853 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001854 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001855 /*
1856 * The previous process is ready to run again. We'll
1857 * let it do so if it is currently in a syscall. This
1858 * heuristic improves the readability of the trace.
1859 */
1860 tcp = pfd2tcb(pollv[last].fd);
1861 if (tcp && (tcp->flags & TCB_INSYSCALL))
1862 return pollv[last].fd;
1863 }
1864
1865 for (i = 0; i < nprocs; i++) {
1866 /* Let competing children run round robin. */
1867 j = (i + last + 1) % nprocs;
1868 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1869 tcp = pfd2tcb(pollv[j].fd);
1870 if (!tcp) {
1871 fprintf(stderr, "strace: lost proc\n");
1872 exit(1);
1873 }
1874 droptcb(tcp);
1875 return -1;
1876 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001877 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878 last = j;
1879 return pollv[j].fd;
1880 }
1881 }
1882 fprintf(stderr, "strace: nothing ready\n");
1883 exit(1);
1884}
1885
1886static int
1887trace()
1888{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001889#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001890 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001891#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001892 struct tcb *tcp;
1893 int pfd;
1894 int what;
1895 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001896 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897
1898 for (;;) {
1899 if (interactive)
1900 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1901
1902 if (nprocs == 0)
1903 break;
1904
1905 switch (nprocs) {
1906 case 1:
1907#ifndef HAVE_POLLABLE_PROCFS
1908 if (proc_poll_pipe[0] == -1) {
1909#endif
1910 tcp = pid2tcb(0);
1911 if (!tcp)
1912 continue;
1913 pfd = tcp->pfd;
1914 if (pfd == -1)
1915 continue;
1916 break;
1917#ifndef HAVE_POLLABLE_PROCFS
1918 }
1919 /* fall through ... */
1920#endif /* !HAVE_POLLABLE_PROCFS */
1921 default:
1922#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001923#ifdef POLL_HACK
1924 /* On some systems (e.g. UnixWare) we get too much ugly
1925 "unfinished..." stuff when multiple proceses are in
1926 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001927
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001928 if (in_syscall) {
1929 struct pollfd pv;
1930 tcp = in_syscall;
1931 in_syscall = NULL;
1932 pv.fd = tcp->pfd;
1933 pv.events = POLLWANT;
1934 if ((what = poll (&pv, 1, 1)) < 0) {
1935 if (interrupted)
1936 return 0;
1937 continue;
1938 }
1939 else if (what == 1 && pv.revents & POLLWANT) {
1940 goto FOUND;
1941 }
1942 }
1943#endif
1944
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945 if (poll(pollv, nprocs, INFTIM) < 0) {
1946 if (interrupted)
1947 return 0;
1948 continue;
1949 }
1950#else /* !HAVE_POLLABLE_PROCFS */
1951 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1952 if (interrupted)
1953 return 0;
1954 continue;
1955 }
1956#endif /* !HAVE_POLLABLE_PROCFS */
1957 pfd = choose_pfd();
1958 if (pfd == -1)
1959 continue;
1960 break;
1961 }
1962
1963 /* Look up `pfd' in our table. */
1964 if ((tcp = pfd2tcb(pfd)) == NULL) {
1965 fprintf(stderr, "unknown pfd: %u\n", pfd);
1966 exit(1);
1967 }
John Hughesb6643082002-05-23 11:02:22 +00001968#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001969 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001970#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971 /* Get the status of the process. */
1972 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001973#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001974 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001975#else /* FREEBSD */
1976 /* Thanks to some scheduling mystery, the first poller
1977 sometimes waits for the already processed end of fork
1978 event. Doing a non blocking poll here solves the problem. */
1979 if (proc_poll_pipe[0] != -1)
1980 ioctl_result = IOCTL_STATUS (tcp);
1981 else
1982 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001983#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984 ioctl_errno = errno;
1985#ifndef HAVE_POLLABLE_PROCFS
1986 if (proc_poll_pipe[0] != -1) {
1987 if (ioctl_result < 0)
1988 kill(poller_pid, SIGKILL);
1989 else
1990 kill(poller_pid, SIGUSR1);
1991 }
1992#endif /* !HAVE_POLLABLE_PROCFS */
1993 }
1994 if (interrupted)
1995 return 0;
1996
1997 if (interactive)
1998 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1999
2000 if (ioctl_result < 0) {
2001 /* Find out what happened if it failed. */
2002 switch (ioctl_errno) {
2003 case EINTR:
2004 case EBADF:
2005 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002006#ifdef FREEBSD
2007 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002008#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 case ENOENT:
2010 droptcb(tcp);
2011 continue;
2012 default:
2013 perror("PIOCWSTOP");
2014 exit(1);
2015 }
2016 }
2017
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002018#ifdef FREEBSD
2019 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2020 /* discard first event for a syscall we never entered */
2021 IOCTL (tcp->pfd, PIOCRUN, 0);
2022 continue;
2023 }
Roland McGrath553a6092002-12-16 20:40:39 +00002024#endif
2025
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026 /* clear the just started flag */
2027 tcp->flags &= ~TCB_STARTUP;
2028
2029 /* set current output file */
2030 outf = tcp->outf;
2031
2032 if (cflag) {
2033 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002034#ifdef FREEBSD
2035 char buf[1024];
2036 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002038 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2039 buf[len] = '\0';
2040 sscanf(buf,
2041 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2042 &stime.tv_sec, &stime.tv_usec);
2043 } else
2044 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002045#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2047 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002048#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2050 tcp->stime = stime;
2051 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002052 what = tcp->status.PR_WHAT;
2053 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002054#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002056 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2057 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058 if (trace_syscall(tcp) < 0) {
2059 fprintf(stderr, "syscall trouble\n");
2060 exit(1);
2061 }
2062 }
2063 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002064#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002066#ifdef POLL_HACK
2067 in_syscall = tcp;
2068#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002069 case PR_SYSEXIT:
2070 if (trace_syscall(tcp) < 0) {
2071 fprintf(stderr, "syscall trouble\n");
2072 exit(1);
2073 }
2074 break;
2075 case PR_SIGNALLED:
2076 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2077 printleader(tcp);
2078 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002079 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002081#ifdef PR_INFO
2082 if (tcp->status.PR_INFO.si_signo == what) {
2083 printleader(tcp);
2084 tprintf(" siginfo=");
2085 printsiginfo(&tcp->status.PR_INFO, 1);
2086 printtrailer(tcp);
2087 }
2088#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002089 }
2090 break;
2091 case PR_FAULTED:
2092 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2093 printleader(tcp);
2094 tprintf("=== FAULT %d ===", what);
2095 printtrailer(tcp);
2096 }
2097 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002098#ifdef FREEBSD
2099 case 0: /* handle case we polled for nothing */
2100 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002101#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002102 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002103 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104 exit(1);
2105 break;
2106 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002107 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002108#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002109 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002110#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002111 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002112#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113 perror("PIOCRUN");
2114 exit(1);
2115 }
2116 }
2117 return 0;
2118}
2119
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002120#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002122#ifdef TCB_GROUP_EXITING
2123/* Handle an exit detach or death signal that is taking all the
2124 related clone threads with it. This is called in three circumstances:
2125 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2126 SIG == 0 Continuing TCP will perform an exit_group syscall.
2127 SIG == other Continuing TCP with SIG will kill the process.
2128*/
2129static int
2130handle_group_exit(struct tcb *tcp, int sig)
2131{
2132 /* We need to locate our records of all the clone threads
2133 related to TCP, either its children or siblings. */
2134 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2135 ? tcp->parent
2136 : tcp->nclone_detached > 0
2137 ? tcp : NULL);
2138
2139 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002140 if (leader != NULL && leader != tcp &&
2141 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002142 fprintf(stderr,
2143 "PANIC: handle_group_exit: %d leader %d\n",
2144 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002145 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002146#ifndef USE_PROCFS
2147 resume_from_tcp (tcp);
2148#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002149 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002150 }
2151 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002152 /* Mark that we are taking the process down. */
2153 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002154 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002155 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002156 if (leader != NULL && leader != tcp)
2157 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002158 }
2159 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2160 perror("strace: ptrace(PTRACE_CONT, ...)");
2161 cleanup();
2162 return -1;
2163 }
2164 else {
Roland McGrath05690952004-10-20 01:00:27 +00002165 if (leader != NULL)
2166 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002167 if (leader != NULL && leader != tcp)
2168 droptcb(tcp);
2169 /* The leader will report to us as parent now,
2170 and then we'll get to the SIG==-1 case. */
2171 return 0;
2172 }
2173 }
2174
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002175 return 0;
2176}
2177#endif
2178
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002179static int
2180trace()
2181{
2182 int pid;
2183 int wait_errno;
2184 int status;
2185 struct tcb *tcp;
2186#ifdef LINUX
2187 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002188#ifdef __WALL
2189 static int wait4_options = __WALL;
2190#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002191#endif /* LINUX */
2192
2193 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002194 if (interrupted)
2195 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 if (interactive)
2197 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2198#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002199#ifdef __WALL
2200 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002201 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002202 /* this kernel does not support __WALL */
2203 wait4_options &= ~__WALL;
2204 errno = 0;
2205 pid = wait4(-1, &status, wait4_options,
2206 cflag ? &ru : NULL);
2207 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002208 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002209 /* most likely a "cloned" process */
2210 pid = wait4(-1, &status, __WCLONE,
2211 cflag ? &ru : NULL);
2212 if (pid == -1) {
2213 fprintf(stderr, "strace: clone wait4 "
2214 "failed: %s\n", strerror(errno));
2215 }
2216 }
2217#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002219#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002220#endif /* LINUX */
2221#ifdef SUNOS4
2222 pid = wait(&status);
2223#endif /* SUNOS4 */
2224 wait_errno = errno;
2225 if (interactive)
2226 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2227
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002228 if (pid == -1) {
2229 switch (wait_errno) {
2230 case EINTR:
2231 continue;
2232 case ECHILD:
2233 /*
2234 * We would like to verify this case
2235 * but sometimes a race in Solbourne's
2236 * version of SunOS sometimes reports
2237 * ECHILD before sending us SIGCHILD.
2238 */
2239#if 0
2240 if (nprocs == 0)
2241 return 0;
2242 fprintf(stderr, "strace: proc miscount\n");
2243 exit(1);
2244#endif
2245 return 0;
2246 default:
2247 errno = wait_errno;
2248 perror("strace: wait");
2249 return -1;
2250 }
2251 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002252 if (pid == popen_pid) {
2253 if (WIFEXITED(status) || WIFSIGNALED(status))
2254 popen_pid = -1;
2255 continue;
2256 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 if (debug)
2258 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2259
2260 /* Look up `pid' in our table. */
2261 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002262#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002263 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002264 /* This is needed to go with the CLONE_PTRACE
2265 changes in process.c/util.c: we might see
2266 the child's initial trap before we see the
2267 parent return from the clone syscall.
2268 Leave the child suspended until the parent
2269 returns from its system call. Only then
2270 will we have the association of parent and
2271 child so that we know how to do clearbpt
2272 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002273 if (nprocs == tcbtabsize &&
2274 expand_tcbtab())
2275 tcp = NULL;
2276 else
2277 tcp = alloctcb(pid);
2278 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002279 kill(pid, SIGKILL); /* XXX */
2280 return 0;
2281 }
2282 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002283 if (!qflag)
2284 fprintf(stderr, "\
2285Process %d attached (waiting for parent)\n",
2286 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002287 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002288 else
2289 /* This can happen if a clone call used
2290 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002291#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002292 {
2293 fprintf(stderr, "unknown pid: %u\n", pid);
2294 if (WIFSTOPPED(status))
2295 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2296 exit(1);
2297 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298 }
2299 /* set current output file */
2300 outf = tcp->outf;
2301 if (cflag) {
2302#ifdef LINUX
2303 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2304 tcp->stime = ru.ru_stime;
2305#endif /* !LINUX */
2306 }
2307
2308 if (tcp->flags & TCB_SUSPENDED) {
2309 /*
2310 * Apparently, doing any ptrace() call on a stopped
2311 * process, provokes the kernel to report the process
2312 * status again on a subsequent wait(), even if the
2313 * process has not been actually restarted.
2314 * Since we have inspected the arguments of suspended
2315 * processes we end up here testing for this case.
2316 */
2317 continue;
2318 }
2319 if (WIFSIGNALED(status)) {
2320 if (!cflag
2321 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2322 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002323 tprintf("+++ killed by %s %s+++",
2324 signame(WTERMSIG(status)),
2325#ifdef WCOREDUMP
2326 WCOREDUMP(status) ? "(core dumped) " :
2327#endif
2328 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 printtrailer(tcp);
2330 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002331#ifdef TCB_GROUP_EXITING
2332 handle_group_exit(tcp, -1);
2333#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002335#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 continue;
2337 }
2338 if (WIFEXITED(status)) {
2339 if (debug)
2340 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002341 if ((tcp->flags & TCB_ATTACHED)
2342#ifdef TCB_GROUP_EXITING
2343 && !(tcp->parent && (tcp->parent->flags &
2344 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002345 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002346#endif
2347 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348 fprintf(stderr,
2349 "PANIC: attached pid %u exited\n",
2350 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002351 if (tcp == tcp_last) {
2352 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2353 == TCB_INSYSCALL)
2354 tprintf(" <unfinished ... exit status %d>\n",
2355 WEXITSTATUS(status));
2356 tcp_last = NULL;
2357 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002358#ifdef TCB_GROUP_EXITING
2359 handle_group_exit(tcp, -1);
2360#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002361 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002362#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363 continue;
2364 }
2365 if (!WIFSTOPPED(status)) {
2366 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2367 droptcb(tcp);
2368 continue;
2369 }
2370 if (debug)
2371 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002372 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002373
Roland McGrath02203312007-06-11 22:06:31 +00002374 /*
2375 * Interestingly, the process may stop
2376 * with STOPSIG equal to some other signal
2377 * than SIGSTOP if we happend to attach
2378 * just before the process takes a signal.
2379 */
2380 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002381 /*
2382 * This flag is there to keep us in sync.
2383 * Next time this process stops it should
2384 * really be entering a system call.
2385 */
2386 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002388 /*
2389 * One example is a breakpoint inherited from
2390 * parent through fork ().
2391 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002392 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2393 droptcb(tcp);
2394 cleanup();
2395 return -1;
2396 }
2397 }
2398 goto tracing;
2399 }
2400
2401 if (WSTOPSIG(status) != SIGTRAP) {
2402 if (WSTOPSIG(status) == SIGSTOP &&
2403 (tcp->flags & TCB_SIGTRAPPED)) {
2404 /*
2405 * Trapped attempt to block SIGTRAP
2406 * Hope we are back in control now.
2407 */
2408 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2409 if (ptrace(PTRACE_SYSCALL,
2410 pid, (char *) 1, 0) < 0) {
2411 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2412 cleanup();
2413 return -1;
2414 }
2415 continue;
2416 }
2417 if (!cflag
2418 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002419 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002420#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002421# define PSR_RI 41
2422 struct siginfo si;
2423 unsigned long psr;
2424
2425 upeek(pid, PT_CR_IPSR, &psr);
2426 upeek(pid, PT_CR_IIP, &pc);
2427
2428 pc += (psr >> PSR_RI) & 0x3;
2429 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2430 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002431#elif defined PTRACE_GETSIGINFO
2432 if (WSTOPSIG(status) == SIGSEGV ||
2433 WSTOPSIG(status) == SIGBUS) {
2434 siginfo_t si;
2435 if (ptrace(PTRACE_GETSIGINFO, pid,
2436 0, &si) == 0)
2437 addr = (unsigned long)
2438 si.si_addr;
2439 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002440#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002441 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002442 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002443 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002444 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 printtrailer(tcp);
2446 }
Roland McGrath05690952004-10-20 01:00:27 +00002447 if (((tcp->flags & TCB_ATTACHED) ||
2448 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002450#ifdef TCB_GROUP_EXITING
2451 handle_group_exit(tcp, WSTOPSIG(status));
2452#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002453 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002454#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002455 continue;
2456 }
2457 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2458 WSTOPSIG(status)) < 0) {
2459 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2460 cleanup();
2461 return -1;
2462 }
2463 tcp->flags &= ~TCB_SUSPENDED;
2464 continue;
2465 }
Roland McGrath02203312007-06-11 22:06:31 +00002466 /* we handled the STATUS, we are permitted to interrupt now. */
2467 if (interrupted)
2468 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002469 if (trace_syscall(tcp) < 0) {
2470 if (tcp->flags & TCB_ATTACHED)
2471 detach(tcp, 0);
2472 else {
2473 ptrace(PTRACE_KILL,
2474 tcp->pid, (char *) 1, SIGTERM);
2475 droptcb(tcp);
2476 }
2477 continue;
2478 }
2479 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002480#ifdef TCB_GROUP_EXITING
2481 if (tcp->flags & TCB_GROUP_EXITING) {
2482 if (handle_group_exit(tcp, 0) < 0)
2483 return -1;
2484 continue;
2485 }
2486#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487 if (tcp->flags & TCB_ATTACHED)
2488 detach(tcp, 0);
2489 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2490 perror("strace: ptrace(PTRACE_CONT, ...)");
2491 cleanup();
2492 return -1;
2493 }
2494 continue;
2495 }
2496 if (tcp->flags & TCB_SUSPENDED) {
2497 if (!qflag)
2498 fprintf(stderr, "Process %u suspended\n", pid);
2499 continue;
2500 }
2501 tracing:
2502 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2503 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2504 cleanup();
2505 return -1;
2506 }
2507 }
2508 return 0;
2509}
2510
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002511#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002512
2513static int curcol;
2514
2515#ifdef __STDC__
2516#include <stdarg.h>
2517#define VA_START(a, b) va_start(a, b)
2518#else
2519#include <varargs.h>
2520#define VA_START(a, b) va_start(a)
2521#endif
2522
2523void
2524#ifdef __STDC__
2525tprintf(const char *fmt, ...)
2526#else
2527tprintf(fmt, va_alist)
2528char *fmt;
2529va_dcl
2530#endif
2531{
2532 va_list args;
2533
2534 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002535 if (outf) {
2536 int n = vfprintf(outf, fmt, args);
2537 if (n < 0 && outf != stderr)
2538 perror(outfname == NULL
2539 ? "<writing to pipe>" : outfname);
2540 else
2541 curcol += n;
2542 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 va_end(args);
2544 return;
2545}
2546
2547void
2548printleader(tcp)
2549struct tcb *tcp;
2550{
2551 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2552 tcp_last->flags |= TCB_REPRINT;
2553 tprintf(" <unfinished ...>\n");
2554 }
2555 curcol = 0;
2556 if ((followfork == 1 || pflag_seen > 1) && outfname)
2557 tprintf("%-5d ", tcp->pid);
2558 else if (nprocs > 1 && !outfname)
2559 tprintf("[pid %5u] ", tcp->pid);
2560 if (tflag) {
2561 char str[sizeof("HH:MM:SS")];
2562 struct timeval tv, dtv;
2563 static struct timeval otv;
2564
2565 gettimeofday(&tv, NULL);
2566 if (rflag) {
2567 if (otv.tv_sec == 0)
2568 otv = tv;
2569 tv_sub(&dtv, &tv, &otv);
2570 tprintf("%6ld.%06ld ",
2571 (long) dtv.tv_sec, (long) dtv.tv_usec);
2572 otv = tv;
2573 }
2574 else if (tflag > 2) {
2575 tprintf("%ld.%06ld ",
2576 (long) tv.tv_sec, (long) tv.tv_usec);
2577 }
2578 else {
2579 time_t local = tv.tv_sec;
2580 strftime(str, sizeof(str), "%T", localtime(&local));
2581 if (tflag > 1)
2582 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2583 else
2584 tprintf("%s ", str);
2585 }
2586 }
2587 if (iflag)
2588 printcall(tcp);
2589}
2590
2591void
2592tabto(col)
2593int col;
2594{
2595 if (curcol < col)
2596 tprintf("%*s", col - curcol, "");
2597}
2598
2599void
2600printtrailer(tcp)
2601struct tcb *tcp;
2602{
2603 tprintf("\n");
2604 tcp_last = NULL;
2605}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002606
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002607#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002608
2609int mp_ioctl (int fd, int cmd, void *arg, int size) {
2610
2611 struct iovec iov[2];
2612 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002613
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002614 iov[0].iov_base = &cmd;
2615 iov[0].iov_len = sizeof cmd;
2616 if (arg) {
2617 ++n;
2618 iov[1].iov_base = arg;
2619 iov[1].iov_len = size;
2620 }
Roland McGrath553a6092002-12-16 20:40:39 +00002621
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002622 return writev (fd, iov, n);
2623}
2624
2625#endif