blob: ce982dc6e5fb7f0835cfbb3012a9942ff54539e4 [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
239static FILE *
240strace_fopen(const char *path, const char *mode)
241{
242 FILE *fp;
243
244 swap_uid();
245 if ((fp = fopen(path, mode)) == NULL)
246 fprintf(stderr, "%s: can't fopen '%s': %s\n",
247 progname, path, strerror(errno));
248 swap_uid();
249 if (fp && set_cloexec_flag(fileno(fp)) < 0)
250 {
251 fclose(fp);
252 fp = NULL;
253 }
254 return fp;
255}
256
257static int popen_pid = -1;
258
259#ifndef _PATH_BSHELL
260# define _PATH_BSHELL "/bin/sh"
261#endif
262
263/*
264 * We cannot use standard popen(3) here because we have to distinguish
265 * popen child process from other processes we trace, and standard popen(3)
266 * does not export its child's pid.
267 */
268static FILE *
269strace_popen(const char *command)
270{
271 int fds[2];
272
273 swap_uid();
274 if (pipe(fds) < 0)
275 {
276 fprintf(stderr, "%s: pipe: %s\n",
277 progname, strerror(errno));
278 swap_uid();
279 return NULL;
280 }
281
282 if (set_cloexec_flag(fds[1]) < 0)
283 {
284 close(fds[0]);
285 close(fds[1]);
286 swap_uid();
287 return NULL;
288 }
289
290 if ((popen_pid = fork()) == -1)
291 {
292 fprintf(stderr, "%s: fork: %s\n",
293 progname, strerror(errno));
294 close(fds[0]);
295 close(fds[1]);
296 swap_uid();
297 return NULL;
298 }
299
300 if (popen_pid)
301 {
302 /* parent */
303 close(fds[0]);
304 swap_uid();
305 return fdopen(fds[1], "w");
306 } else
307 {
308 /* child */
309 close(fds[1]);
310 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
311 {
312 fprintf(stderr, "%s: dup2: %s\n",
313 progname, strerror(errno));
314 _exit(1);
315 }
316 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
317 fprintf(stderr, "%s: execl: %s: %s\n",
318 progname, _PATH_BSHELL, strerror(errno));
319 _exit(1);
320 }
321}
322
323static int
324newoutf(struct tcb *tcp)
325{
326 if (outfname && followfork > 1) {
327 char name[MAXPATHLEN];
328 FILE *fp;
329
330 sprintf(name, "%s.%u", outfname, tcp->pid);
331 if ((fp = strace_fopen(name, "w")) == NULL)
332 return -1;
333 tcp->outf = fp;
334 }
335 return 0;
336}
337
Roland McGrath02203312007-06-11 22:06:31 +0000338static void
339startup_attach(void)
340{
341 int tcbi;
342 struct tcb *tcp;
343
344 /*
345 * Block user interruptions as we would leave the traced
346 * process stopped (process state T) if we would terminate in
347 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
348 * We rely on cleanup () from this point on.
349 */
350 if (interactive)
351 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
352
353 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
354 tcp = tcbtab[tcbi];
355 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
356 continue;
357#ifdef LINUX
358 if (tcp->flags & TCB_CLONE_THREAD)
359 continue;
360#endif
361 /* Reinitialize the output since it may have changed. */
362 tcp->outf = outf;
363 if (newoutf(tcp) < 0)
364 exit(1);
365
366#ifdef USE_PROCFS
367 if (proc_open(tcp, 1) < 0) {
368 fprintf(stderr, "trouble opening proc file\n");
369 droptcb(tcp);
370 continue;
371 }
372#else /* !USE_PROCFS */
373# ifdef LINUX
374 if (followfork) {
375 char procdir[MAXPATHLEN];
376 DIR *dir;
377
378 sprintf(procdir, "/proc/%d/task", tcp->pid);
379 dir = opendir(procdir);
380 if (dir != NULL) {
381 unsigned int ntid = 0, nerr = 0;
382 struct dirent *de;
383 int tid;
384 while ((de = readdir(dir)) != NULL) {
385 if (de->d_fileno == 0 ||
386 de->d_name[0] == '.')
387 continue;
388 tid = atoi(de->d_name);
389 if (tid <= 0)
390 continue;
391 ++ntid;
392 if (ptrace(PTRACE_ATTACH, tid,
393 (char *) 1, 0) < 0)
394 ++nerr;
395 else if (tid != tcbtab[tcbi]->pid) {
396 if (nprocs == tcbtabsize &&
397 expand_tcbtab())
398 tcp = NULL;
399 else
400 tcp = alloctcb(tid);
401 if (tcp == NULL)
402 exit(1);
403 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
404 tcbtab[tcbi]->nchildren++;
405 tcbtab[tcbi]->nclone_threads++;
406 tcbtab[tcbi]->nclone_detached++;
407 tcp->parent = tcbtab[tcbi];
408 }
409 if (interactive) {
410 sigprocmask(SIG_SETMASK, &empty_set, NULL);
411 if (interrupted)
412 return;
413 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
414 }
415 }
416 closedir(dir);
417 if (nerr == ntid) {
418 perror("attach: ptrace(PTRACE_ATTACH, ...)");
419 droptcb(tcp);
420 continue;
421 }
422 if (!qflag) {
423 ntid -= nerr;
424 if (ntid > 1)
425 fprintf(stderr, "\
426Process %u attached with %u threads - interrupt to quit\n",
427 tcp->pid, ntid);
428 else
429 fprintf(stderr, "\
430Process %u attached - interrupt to quit\n",
431 tcp->pid);
432 }
433 continue;
434 }
435 }
436# endif
437 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
438 perror("attach: ptrace(PTRACE_ATTACH, ...)");
439 droptcb(tcp);
440 continue;
441 }
442 /* INTERRUPTED is going to be checked at the top of TRACE. */
443#endif /* !USE_PROCFS */
444 if (!qflag)
445 fprintf(stderr,
446 "Process %u attached - interrupt to quit\n",
447 tcp->pid);
448 }
449
450 if (interactive)
451 sigprocmask(SIG_SETMASK, &empty_set, NULL);
452}
453
454static void
455startup_child (char **argv)
456{
457 struct stat statbuf;
458 const char *filename;
459 char pathname[MAXPATHLEN];
460 int pid = 0;
461 struct tcb *tcp;
462
463 filename = argv[0];
464 if (strchr(filename, '/')) {
465 if (strlen(filename) > sizeof pathname - 1) {
466 errno = ENAMETOOLONG;
467 perror("strace: exec");
468 exit(1);
469 }
470 strcpy(pathname, filename);
471 }
472#ifdef USE_DEBUGGING_EXEC
473 /*
474 * Debuggers customarily check the current directory
475 * first regardless of the path but doing that gives
476 * security geeks a panic attack.
477 */
478 else if (stat(filename, &statbuf) == 0)
479 strcpy(pathname, filename);
480#endif /* USE_DEBUGGING_EXEC */
481 else {
482 char *path;
483 int m, n, len;
484
485 for (path = getenv("PATH"); path && *path; path += m) {
486 if (strchr(path, ':')) {
487 n = strchr(path, ':') - path;
488 m = n + 1;
489 }
490 else
491 m = n = strlen(path);
492 if (n == 0) {
493 if (!getcwd(pathname, MAXPATHLEN))
494 continue;
495 len = strlen(pathname);
496 }
497 else if (n > sizeof pathname - 1)
498 continue;
499 else {
500 strncpy(pathname, path, n);
501 len = n;
502 }
503 if (len && pathname[len - 1] != '/')
504 pathname[len++] = '/';
505 strcpy(pathname + len, filename);
506 if (stat(pathname, &statbuf) == 0 &&
507 /* Accept only regular files
508 with some execute bits set.
509 XXX not perfect, might still fail */
510 S_ISREG(statbuf.st_mode) &&
511 (statbuf.st_mode & 0111))
512 break;
513 }
514 }
515 if (stat(pathname, &statbuf) < 0) {
516 fprintf(stderr, "%s: %s: command not found\n",
517 progname, filename);
518 exit(1);
519 }
520 switch (pid = fork()) {
521 case -1:
522 perror("strace: fork");
523 cleanup();
524 exit(1);
525 break;
526 case 0: {
527#ifdef USE_PROCFS
528 if (outf != stderr) close (fileno (outf));
529#ifdef MIPS
530 /* Kludge for SGI, see proc_open for details. */
531 sa.sa_handler = foobar;
532 sa.sa_flags = 0;
533 sigemptyset(&sa.sa_mask);
534 sigaction(SIGINT, &sa, NULL);
535#endif /* MIPS */
536#ifndef FREEBSD
537 pause();
538#else /* FREEBSD */
539 kill(getpid(), SIGSTOP); /* stop HERE */
540#endif /* FREEBSD */
541#else /* !USE_PROCFS */
542 if (outf!=stderr)
543 close(fileno (outf));
544
545 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
546 perror("strace: ptrace(PTRACE_TRACEME, ...)");
547 exit(1);
548 }
549 if (debug)
550 kill(getpid(), SIGSTOP);
551
552 if (username != NULL || geteuid() == 0) {
553 uid_t run_euid = run_uid;
554 gid_t run_egid = run_gid;
555
556 if (statbuf.st_mode & S_ISUID)
557 run_euid = statbuf.st_uid;
558 if (statbuf.st_mode & S_ISGID)
559 run_egid = statbuf.st_gid;
560
561 /*
562 * It is important to set groups before we
563 * lose privileges on setuid.
564 */
565 if (username != NULL) {
566 if (initgroups(username, run_gid) < 0) {
567 perror("initgroups");
568 exit(1);
569 }
570 if (setregid(run_gid, run_egid) < 0) {
571 perror("setregid");
572 exit(1);
573 }
574 if (setreuid(run_uid, run_euid) < 0) {
575 perror("setreuid");
576 exit(1);
577 }
578 }
579 }
580 else
581 setreuid(run_uid, run_uid);
582
583 /*
584 * Induce an immediate stop so that the parent
585 * will resume us with PTRACE_SYSCALL and display
586 * this execve call normally.
587 */
588 kill(getpid(), SIGSTOP);
589#endif /* !USE_PROCFS */
590
591 execv(pathname, argv);
592 perror("strace: exec");
593 _exit(1);
594 break;
595 }
596 default:
597 if ((tcp = alloctcb(pid)) == NULL) {
598 cleanup();
599 exit(1);
600 }
601#ifdef USE_PROCFS
602 if (proc_open(tcp, 0) < 0) {
603 fprintf(stderr, "trouble opening proc file\n");
604 cleanup();
605 exit(1);
606 }
607#endif /* USE_PROCFS */
608 break;
609 }
610}
611
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000612int
613main(argc, argv)
614int argc;
615char *argv[];
616{
617 extern int optind;
618 extern char *optarg;
619 struct tcb *tcp;
620 int c, pid = 0;
621 struct sigaction sa;
622
623 static char buf[BUFSIZ];
624
Roland McGrathee9d4352002-12-18 04:16:10 +0000625 /* Allocate the initial tcbtab. */
626 tcbtabsize = argc; /* Surely enough for all -p args. */
627 tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
628 tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
629 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
630 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
631
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000632 progname = argv[0];
633 outf = stderr;
634 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000635 set_sortby(DEFAULT_SORTBY);
636 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000637 qualify("trace=all");
638 qualify("abbrev=all");
639 qualify("verbose=all");
640 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000641 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000642 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000643 switch (c) {
644 case 'c':
645 cflag++;
646 dtime++;
647 break;
648 case 'd':
649 debug++;
650 break;
651 case 'f':
652 followfork++;
653 break;
654 case 'F':
655 followvfork++;
656 break;
657 case 'h':
658 usage(stdout, 0);
659 break;
660 case 'i':
661 iflag++;
662 break;
663 case 'q':
664 qflag++;
665 break;
666 case 'r':
667 rflag++;
668 tflag++;
669 break;
670 case 't':
671 tflag++;
672 break;
673 case 'T':
674 dtime++;
675 break;
676 case 'x':
677 xflag++;
678 break;
679 case 'v':
680 qualify("abbrev=none");
681 break;
682 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000683 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684 exit(0);
685 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000686 case 'z':
687 not_failing_only = 1;
688 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689 case 'a':
690 acolumn = atoi(optarg);
691 break;
692 case 'e':
693 qualify(optarg);
694 break;
695 case 'o':
696 outfname = strdup(optarg);
697 break;
698 case 'O':
699 set_overhead(atoi(optarg));
700 break;
701 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000702 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703 fprintf(stderr, "%s: Invalid process id: %s\n",
704 progname, optarg);
705 break;
706 }
707 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000708 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000709 break;
710 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000711 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000712 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713 progname);
714 exit(1);
715 }
716 tcp->flags |= TCB_ATTACHED;
717 pflag_seen++;
718 break;
719 case 's':
720 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000721 if (max_strlen < 0) {
722 fprintf(stderr,
723 "%s: invalid -s argument: %s\n",
724 progname, optarg);
725 exit(1);
726 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000727 break;
728 case 'S':
729 set_sortby(optarg);
730 break;
731 case 'u':
732 username = strdup(optarg);
733 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000734 case 'E':
735 if (putenv(optarg) < 0) {
736 fprintf(stderr, "%s: out of memory\n",
737 progname);
738 exit(1);
739 }
740 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000741 default:
742 usage(stderr, 1);
743 break;
744 }
745 }
746
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000747 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000748 usage(stderr, 1);
749
Roland McGrathcb9def62006-04-25 07:48:03 +0000750 if (followfork > 1 && cflag) {
751 fprintf(stderr,
752 "%s: -c and -ff are mutually exclusive options\n",
753 progname);
754 exit(1);
755 }
756
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 /* See if they want to run as another user. */
758 if (username != NULL) {
759 struct passwd *pent;
760
761 if (getuid() != 0 || geteuid() != 0) {
762 fprintf(stderr,
763 "%s: you must be root to use the -u option\n",
764 progname);
765 exit(1);
766 }
767 if ((pent = getpwnam(username)) == NULL) {
768 fprintf(stderr, "%s: cannot find user `%s'\n",
769 progname, optarg);
770 exit(1);
771 }
772 run_uid = pent->pw_uid;
773 run_gid = pent->pw_gid;
774 }
775 else {
776 run_uid = getuid();
777 run_gid = getgid();
778 }
779
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000780 /* Check if they want to redirect the output. */
781 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000782 /* See if they want to pipe the output. */
783 if (outfname[0] == '|' || outfname[0] == '!') {
784 /*
785 * We can't do the <outfname>.PID funny business
786 * when using popen, so prohibit it.
787 */
788 if (followfork > 1) {
789 fprintf(stderr, "\
790%s: piping the output and -ff are mutually exclusive options\n",
791 progname);
792 exit(1);
793 }
794
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000795 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000796 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000797 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000798 else if (followfork <= 1 &&
799 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801 }
802
Roland McGrath37b9a662003-11-07 02:26:54 +0000803 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000804 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000805 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000807 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000808 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000809
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000810 sigemptyset(&empty_set);
811 sigemptyset(&blocked_set);
812 sa.sa_handler = SIG_IGN;
813 sigemptyset(&sa.sa_mask);
814 sa.sa_flags = 0;
815 sigaction(SIGTTOU, &sa, NULL);
816 sigaction(SIGTTIN, &sa, NULL);
817 if (interactive) {
818 sigaddset(&blocked_set, SIGHUP);
819 sigaddset(&blocked_set, SIGINT);
820 sigaddset(&blocked_set, SIGQUIT);
821 sigaddset(&blocked_set, SIGPIPE);
822 sigaddset(&blocked_set, SIGTERM);
823 sa.sa_handler = interrupt;
824#ifdef SUNOS4
825 /* POSIX signals on sunos4.1 are a little broken. */
826 sa.sa_flags = SA_INTERRUPT;
827#endif /* SUNOS4 */
828 }
829 sigaction(SIGHUP, &sa, NULL);
830 sigaction(SIGINT, &sa, NULL);
831 sigaction(SIGQUIT, &sa, NULL);
832 sigaction(SIGPIPE, &sa, NULL);
833 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000834#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000835 sa.sa_handler = reaper;
836 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000837#else
838 /* Make sure SIGCHLD has the default action so that waitpid
839 definitely works without losing track of children. The user
840 should not have given us a bogus state to inherit, but he might
841 have. Arguably we should detect SIG_IGN here and pass it on
842 to children, but probably noone really needs that. */
843 sa.sa_handler = SIG_DFL;
844 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000845#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000846
Roland McGrath02203312007-06-11 22:06:31 +0000847 if (pflag_seen)
848 startup_attach();
849 else
850 startup_child(&argv[optind]);
851
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000852 if (trace() < 0)
853 exit(1);
854 cleanup();
855 exit(0);
856}
857
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000858int
859expand_tcbtab()
860{
861 /* Allocate some more TCBs and expand the table.
862 We don't want to relocate the TCBs because our
863 callers have pointers and it would be a pain.
864 So tcbtab is a table of pointers. Since we never
865 free the TCBs, we allocate a single chunk of many. */
866 struct tcb **newtab = (struct tcb **)
867 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
868 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
869 sizeof *newtcbs);
870 int i;
871 if (newtab == NULL || newtcbs == NULL) {
872 if (newtab != NULL)
873 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000874 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
875 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000876 return 1;
877 }
878 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
879 newtab[i] = &newtcbs[i - tcbtabsize];
880 tcbtabsize *= 2;
881 tcbtab = newtab;
882
883 return 0;
884}
885
886
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000887struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000888alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889{
890 int i;
891 struct tcb *tcp;
892
Roland McGrathee9d4352002-12-18 04:16:10 +0000893 for (i = 0; i < tcbtabsize; i++) {
894 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895 if ((tcp->flags & TCB_INUSE) == 0) {
896 tcp->pid = pid;
897 tcp->parent = NULL;
898 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000899 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000900#ifdef TCB_CLONE_THREAD
901 tcp->nclone_threads = tcp->nclone_detached = 0;
902 tcp->nclone_waiting = 0;
903#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000904 tcp->flags = TCB_INUSE | TCB_STARTUP;
905 tcp->outf = outf; /* Initialise to current out file */
906 tcp->stime.tv_sec = 0;
907 tcp->stime.tv_usec = 0;
908 tcp->pfd = -1;
909 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000910 if (command_options_parsed)
911 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 return tcp;
913 }
914 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000915 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 return NULL;
917}
918
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000919#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000920int
921proc_open(tcp, attaching)
922struct tcb *tcp;
923int attaching;
924{
925 char proc[32];
926 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000927#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000928 int i;
929 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000930 sigset_t signals;
931 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000932#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933#ifndef HAVE_POLLABLE_PROCFS
934 static int last_pfd;
935#endif
936
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000937#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000938 /* Open the process pseudo-files in /proc. */
939 sprintf(proc, "/proc/%d/ctl", tcp->pid);
940 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 perror("strace: open(\"/proc/...\", ...)");
942 return -1;
943 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000944 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 return -1;
946 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000947 sprintf(proc, "/proc/%d/status", tcp->pid);
948 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
949 perror("strace: open(\"/proc/...\", ...)");
950 return -1;
951 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000952 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000953 return -1;
954 }
955 sprintf(proc, "/proc/%d/as", tcp->pid);
956 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
957 perror("strace: open(\"/proc/...\", ...)");
958 return -1;
959 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000960 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000961 return -1;
962 }
963#else
964 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000965#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000966 sprintf(proc, "/proc/%d", tcp->pid);
967 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000968#else /* FREEBSD */
969 sprintf(proc, "/proc/%d/mem", tcp->pid);
970 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
971#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000972 perror("strace: open(\"/proc/...\", ...)");
973 return -1;
974 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000975 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000976 return -1;
977 }
978#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000979#ifdef FREEBSD
980 sprintf(proc, "/proc/%d/regs", tcp->pid);
981 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
982 perror("strace: open(\"/proc/.../regs\", ...)");
983 return -1;
984 }
985 if (cflag) {
986 sprintf(proc, "/proc/%d/status", tcp->pid);
987 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
988 perror("strace: open(\"/proc/.../status\", ...)");
989 return -1;
990 }
991 } else
992 tcp->pfd_status = -1;
993#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000994 rebuild_pollv();
995 if (!attaching) {
996 /*
997 * Wait for the child to pause. Because of a race
998 * condition we have to poll for the event.
999 */
1000 for (;;) {
1001 if (IOCTL_STATUS (tcp) < 0) {
1002 perror("strace: PIOCSTATUS");
1003 return -1;
1004 }
1005 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001006 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001007 }
1008 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001009#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001010 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001011 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001012 perror("strace: PIOCSTOP");
1013 return -1;
1014 }
Roland McGrath553a6092002-12-16 20:40:39 +00001015#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016#ifdef PIOCSET
1017 /* Set Run-on-Last-Close. */
1018 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001019 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020 perror("PIOCSET PR_RLC");
1021 return -1;
1022 }
1023 /* Set or Reset Inherit-on-Fork. */
1024 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001025 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 perror("PIOC{SET,RESET} PR_FORK");
1027 return -1;
1028 }
1029#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001030#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1032 perror("PIOCSRLC");
1033 return -1;
1034 }
1035 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1036 perror("PIOC{S,R}FORK");
1037 return -1;
1038 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001039#else /* FREEBSD */
1040 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1041 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1042 perror("PIOCGFL");
1043 return -1;
1044 }
1045 arg &= ~PF_LINGER;
1046 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1047 perror("PIOCSFL");
1048 return -1;
1049 }
1050#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001052#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001053 /* Enable all syscall entries we care about. */
1054 premptyset(&syscalls);
1055 for (i = 1; i < MAX_QUALS; ++i) {
1056 if (i > (sizeof syscalls) * CHAR_BIT) break;
1057 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1058 }
1059 praddset (&syscalls, SYS_execve);
1060 if (followfork) {
1061 praddset (&syscalls, SYS_fork);
1062#ifdef SYS_forkall
1063 praddset (&syscalls, SYS_forkall);
1064#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001065#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001066 praddset (&syscalls, SYS_fork1);
1067#endif
1068#ifdef SYS_rfork1
1069 praddset (&syscalls, SYS_rfork1);
1070#endif
1071#ifdef SYS_rforkall
1072 praddset (&syscalls, SYS_rforkall);
1073#endif
1074 }
1075 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 perror("PIOCSENTRY");
1077 return -1;
1078 }
John Hughes19e49982001-10-19 08:59:12 +00001079 /* Enable the syscall exits. */
1080 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 perror("PIOSEXIT");
1082 return -1;
1083 }
John Hughes19e49982001-10-19 08:59:12 +00001084 /* Enable signals we care about. */
1085 premptyset(&signals);
1086 for (i = 1; i < MAX_QUALS; ++i) {
1087 if (i > (sizeof signals) * CHAR_BIT) break;
1088 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1089 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001090 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 perror("PIOCSTRACE");
1092 return -1;
1093 }
John Hughes19e49982001-10-19 08:59:12 +00001094 /* Enable faults we care about */
1095 premptyset(&faults);
1096 for (i = 1; i < MAX_QUALS; ++i) {
1097 if (i > (sizeof faults) * CHAR_BIT) break;
1098 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1099 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001100 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 perror("PIOCSFAULT");
1102 return -1;
1103 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001104#else /* FREEBSD */
1105 /* set events flags. */
1106 arg = S_SIG | S_SCE | S_SCX ;
1107 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1108 perror("PIOCBIS");
1109 return -1;
1110 }
1111#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 if (!attaching) {
1113#ifdef MIPS
1114 /*
1115 * The SGI PRSABORT doesn't work for pause() so
1116 * we send it a caught signal to wake it up.
1117 */
1118 kill(tcp->pid, SIGINT);
1119#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001120#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001122 arg = PRSABORT;
1123 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 perror("PIOCRUN");
1125 return -1;
1126 }
Roland McGrath553a6092002-12-16 20:40:39 +00001127#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001128#endif /* !MIPS*/
1129#ifdef FREEBSD
1130 /* wake up the child if it received the SIGSTOP */
1131 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001132#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 for (;;) {
1134 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001135 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 perror("PIOCWSTOP");
1137 return -1;
1138 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001139 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001140 tcp->flags &= ~TCB_INSYSCALL;
1141 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001142 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 break;
1144 }
1145 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001146#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001147 arg = 0;
1148 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001149#else /* FREEBSD */
1150 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001151#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 perror("PIOCRUN");
1153 return -1;
1154 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001155#ifdef FREEBSD
1156 /* handle the case where we "opened" the child before
1157 it did the kill -STOP */
1158 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1159 tcp->status.PR_WHAT == SIGSTOP)
1160 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001163#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001165#else /* FREEBSD */
1166 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001167 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001168 /* We are attaching to an already running process.
1169 * Try to figure out the state of the process in syscalls,
1170 * to handle the first event well.
1171 * This is done by having a look at the "wchan" property of the
1172 * process, which tells where it is stopped (if it is). */
1173 FILE * status;
1174 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001175
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001176 sprintf(proc, "/proc/%d/status", tcp->pid);
1177 status = fopen(proc, "r");
1178 if (status &&
1179 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1180 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1181 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1182 strcmp(wchan, "stopevent")) {
1183 /* The process is asleep in the middle of a syscall.
1184 Fake the syscall entry event */
1185 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1186 tcp->status.PR_WHY = PR_SYSENTRY;
1187 trace_syscall(tcp);
1188 }
1189 if (status)
1190 fclose(status);
1191 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001192 }
1193#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194#ifndef HAVE_POLLABLE_PROCFS
1195 if (proc_poll_pipe[0] != -1)
1196 proc_poller(tcp->pfd);
1197 else if (nprocs > 1) {
1198 proc_poll_open();
1199 proc_poller(last_pfd);
1200 proc_poller(tcp->pfd);
1201 }
1202 last_pfd = tcp->pfd;
1203#endif /* !HAVE_POLLABLE_PROCFS */
1204 return 0;
1205}
1206
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001207#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001209struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210pid2tcb(pid)
1211int pid;
1212{
1213 int i;
1214 struct tcb *tcp;
1215
Roland McGrathee9d4352002-12-18 04:16:10 +00001216 for (i = 0; i < tcbtabsize; i++) {
1217 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218 if (pid && tcp->pid != pid)
1219 continue;
1220 if (tcp->flags & TCB_INUSE)
1221 return tcp;
1222 }
1223 return NULL;
1224}
1225
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001226#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227
1228static struct tcb *
1229pfd2tcb(pfd)
1230int pfd;
1231{
1232 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233
Roland McGrathca16be82003-01-10 19:55:28 +00001234 for (i = 0; i < tcbtabsize; i++) {
1235 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 if (tcp->pfd != pfd)
1237 continue;
1238 if (tcp->flags & TCB_INUSE)
1239 return tcp;
1240 }
1241 return NULL;
1242}
1243
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001244#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245
1246void
1247droptcb(tcp)
1248struct tcb *tcp;
1249{
1250 if (tcp->pid == 0)
1251 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001252#ifdef TCB_CLONE_THREAD
1253 if (tcp->nclone_threads > 0) {
1254 /* There are other threads left in this process, but this
1255 is the one whose PID represents the whole process.
1256 We need to keep this record around as a zombie until
1257 all the threads die. */
1258 tcp->flags |= TCB_EXITING;
1259 return;
1260 }
1261#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 nprocs--;
1263 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001264
Roland McGrathe29341c2003-01-10 20:14:20 +00001265 if (tcp->parent != NULL) {
1266 tcp->parent->nchildren--;
1267#ifdef TCB_CLONE_THREAD
1268 if (tcp->flags & TCB_CLONE_DETACHED)
1269 tcp->parent->nclone_detached--;
1270 if (tcp->flags & TCB_CLONE_THREAD)
1271 tcp->parent->nclone_threads--;
1272#endif
Roland McGrath09623452003-05-23 02:27:13 +00001273#ifdef TCB_CLONE_DETACHED
1274 if (!(tcp->flags & TCB_CLONE_DETACHED))
1275#endif
1276 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001277 tcp->parent = NULL;
1278 }
1279
1280 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281 if (tcp->pfd != -1) {
1282 close(tcp->pfd);
1283 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001284#ifdef FREEBSD
1285 if (tcp->pfd_reg != -1) {
1286 close(tcp->pfd_reg);
1287 tcp->pfd_reg = -1;
1288 }
1289 if (tcp->pfd_status != -1) {
1290 close(tcp->pfd_status);
1291 tcp->pfd_status = -1;
1292 }
Roland McGrath553a6092002-12-16 20:40:39 +00001293#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001294#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001295 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296#endif
1297 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001298
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001299 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001300 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001301
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 tcp->outf = 0;
1303}
1304
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001305#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306
1307static int
1308resume(tcp)
1309struct tcb *tcp;
1310{
1311 if (tcp == NULL)
1312 return -1;
1313
1314 if (!(tcp->flags & TCB_SUSPENDED)) {
1315 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1316 return -1;
1317 }
1318 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001319#ifdef TCB_CLONE_THREAD
1320 if (tcp->flags & TCB_CLONE_THREAD)
1321 tcp->parent->nclone_waiting--;
1322#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323
1324 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1325 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1326 return -1;
1327 }
1328
1329 if (!qflag)
1330 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1331 return 0;
1332}
1333
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001334#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335
Roland McGrath0a463882007-07-05 18:43:16 +00001336/* detach traced process; continue with sig
1337 Never call DETACH twice on the same process as both unattached and
1338 attached-unstopped processes give the same ESRCH. For unattached process we
1339 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340
1341static int
1342detach(tcp, sig)
1343struct tcb *tcp;
1344int sig;
1345{
1346 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001347#ifdef LINUX
Roland McGrath02203312007-06-11 22:06:31 +00001348 int status, resumed, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001349 struct tcb *zombie = NULL;
1350
1351 /* If the group leader is lingering only because of this other
1352 thread now dying, then detach the leader as well. */
1353 if ((tcp->flags & TCB_CLONE_THREAD) &&
1354 tcp->parent->nclone_threads == 1 &&
1355 (tcp->parent->flags & TCB_EXITING))
1356 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001357#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358
1359 if (tcp->flags & TCB_BPTSET)
1360 sig = SIGKILL;
1361
1362#ifdef LINUX
1363 /*
1364 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001365 * before detaching. Arghh. We go through hoops
1366 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001367 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001368#if defined(SPARC)
1369#undef PTRACE_DETACH
1370#define PTRACE_DETACH PTRACE_SUNDETACH
1371#endif
Roland McGrath02203312007-06-11 22:06:31 +00001372 /*
1373 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1374 * expected SIGSTOP. We must catch exactly one as otherwise the
1375 * detached process would be left stopped (process state T).
1376 */
1377 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1379 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001380 }
1381 else if (errno != ESRCH) {
1382 /* Shouldn't happen. */
1383 perror("detach: ptrace(PTRACE_DETACH, ...)");
1384 }
Roland McGrath134813a2007-06-02 00:07:33 +00001385 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1386 : tcp->pid),
1387 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001388 if (errno != ESRCH)
1389 perror("detach: checking sanity");
1390 }
Roland McGrath02203312007-06-11 22:06:31 +00001391 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1392 ? tcp->parent->pid : tcp->pid),
1393 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001394 if (errno != ESRCH)
1395 perror("detach: stopping child");
1396 }
Roland McGrath02203312007-06-11 22:06:31 +00001397 else
1398 catch_sigstop = 1;
1399 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001400 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001401#ifdef __WALL
1402 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1403 if (errno == ECHILD) /* Already gone. */
1404 break;
1405 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001406 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001407 break;
1408 }
1409#endif /* __WALL */
1410 /* No __WALL here. */
1411 if (waitpid(tcp->pid, &status, 0) < 0) {
1412 if (errno != ECHILD) {
1413 perror("detach: waiting");
1414 break;
1415 }
1416#ifdef __WCLONE
1417 /* If no processes, try clones. */
1418 if (wait4(tcp->pid, &status, __WCLONE,
1419 NULL) < 0) {
1420 if (errno != ECHILD)
1421 perror("detach: waiting");
1422 break;
1423 }
1424#endif /* __WCLONE */
1425 }
1426#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001427 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001428#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001429 if (!WIFSTOPPED(status)) {
1430 /* Au revoir, mon ami. */
1431 break;
1432 }
1433 if (WSTOPSIG(status) == SIGSTOP) {
1434 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001435 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 if (errno != ESRCH)
1437 perror("detach: ptrace(PTRACE_DETACH, ...)");
1438 /* I died trying. */
1439 }
1440 break;
1441 }
1442 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001443 WSTOPSIG(status) == SIGTRAP ?
1444 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 if (errno != ESRCH)
1446 perror("detach: ptrace(PTRACE_CONT, ...)");
1447 break;
1448 }
1449 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001450#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451
1452#if defined(SUNOS4)
1453 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1454 if (sig && kill(tcp->pid, sig) < 0)
1455 perror("detach: kill");
1456 sig = 0;
1457 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1458 perror("detach: ptrace(PTRACE_DETACH, ...)");
1459#endif /* SUNOS4 */
1460
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001461#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001462 resumed = 0;
1463
1464 /* XXX This won't always be quite right (but it never was).
1465 A waiter with argument 0 or < -1 is waiting for any pid in
1466 a particular pgrp, which this child might or might not be
1467 in. The waiter will only wake up if it's argument is -1
1468 or if it's waiting for tcp->pid's pgrp. It makes a
1469 difference to wake up a waiter when there might be more
1470 traced children, because it could get a false ECHILD
1471 error. OTOH, if this was the last child in the pgrp, then
1472 it ought to wake up and get ECHILD. We would have to
1473 search the system for all pid's in the pgrp to be sure.
1474
1475 && (t->waitpid == -1 ||
1476 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1477 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1478 */
1479
1480 if (tcp->parent &&
1481 (tcp->parent->flags & TCB_SUSPENDED) &&
1482 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1483 error = resume(tcp->parent);
1484 ++resumed;
1485 }
1486#ifdef TCB_CLONE_THREAD
1487 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1488 /* Some other threads of our parent are waiting too. */
1489 unsigned int i;
1490
1491 /* Resume all the threads that were waiting for this PID. */
1492 for (i = 0; i < tcbtabsize; i++) {
1493 struct tcb *t = tcbtab[i];
1494 if (t->parent == tcp->parent && t != tcp
1495 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1496 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1497 && t->waitpid == tcp->pid) {
1498 error |= resume (t);
1499 ++resumed;
1500 }
1501 }
1502 if (resumed == 0)
1503 /* Noone was waiting for this PID in particular,
1504 so now we might need to resume some wildcarders. */
1505 for (i = 0; i < tcbtabsize; i++) {
1506 struct tcb *t = tcbtab[i];
1507 if (t->parent == tcp->parent && t != tcp
1508 && ((t->flags
1509 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1510 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1511 && t->waitpid <= 0
1512 ) {
1513 error |= resume (t);
1514 break;
1515 }
1516 }
1517 }
1518#endif
1519
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001520#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521
1522 if (!qflag)
1523 fprintf(stderr, "Process %u detached\n", tcp->pid);
1524
1525 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001526
1527#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001528 if (zombie != NULL) {
1529 /* TCP no longer exists therefore you must not detach () it. */
1530 droptcb(zombie);
1531 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001532#endif
1533
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 return error;
1535}
1536
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001537#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538
1539static void
1540reaper(sig)
1541int sig;
1542{
1543 int pid;
1544 int status;
1545
1546 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1547#if 0
1548 struct tcb *tcp;
1549
1550 tcp = pid2tcb(pid);
1551 if (tcp)
1552 droptcb(tcp);
1553#endif
1554 }
1555}
1556
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001557#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558
1559static void
1560cleanup()
1561{
1562 int i;
1563 struct tcb *tcp;
1564
Roland McGrathee9d4352002-12-18 04:16:10 +00001565 for (i = 0; i < tcbtabsize; i++) {
1566 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 if (!(tcp->flags & TCB_INUSE))
1568 continue;
1569 if (debug)
1570 fprintf(stderr,
1571 "cleanup: looking at pid %u\n", tcp->pid);
1572 if (tcp_last &&
1573 (!outfname || followfork < 2 || tcp_last == tcp)) {
1574 tprintf(" <unfinished ...>\n");
1575 tcp_last = NULL;
1576 }
1577 if (tcp->flags & TCB_ATTACHED)
1578 detach(tcp, 0);
1579 else {
1580 kill(tcp->pid, SIGCONT);
1581 kill(tcp->pid, SIGTERM);
1582 }
1583 }
1584 if (cflag)
1585 call_summary(outf);
1586}
1587
1588static void
1589interrupt(sig)
1590int sig;
1591{
1592 interrupted = 1;
1593}
1594
1595#ifndef HAVE_STRERROR
1596
Roland McGrath6d2b3492002-12-30 00:51:30 +00001597#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598extern int sys_nerr;
1599extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001600#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601
1602const char *
1603strerror(errno)
1604int errno;
1605{
1606 static char buf[64];
1607
1608 if (errno < 1 || errno >= sys_nerr) {
1609 sprintf(buf, "Unknown error %d", errno);
1610 return buf;
1611 }
1612 return sys_errlist[errno];
1613}
1614
1615#endif /* HAVE_STERRROR */
1616
1617#ifndef HAVE_STRSIGNAL
1618
Roland McGrath8f474e02003-01-14 07:53:33 +00001619#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001620extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001622#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1623extern char *_sys_siglist[];
1624#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625
1626const char *
1627strsignal(sig)
1628int sig;
1629{
1630 static char buf[64];
1631
1632 if (sig < 1 || sig >= NSIG) {
1633 sprintf(buf, "Unknown signal %d", sig);
1634 return buf;
1635 }
1636#ifdef HAVE__SYS_SIGLIST
1637 return _sys_siglist[sig];
1638#else
1639 return sys_siglist[sig];
1640#endif
1641}
1642
1643#endif /* HAVE_STRSIGNAL */
1644
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001645#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646
1647static void
1648rebuild_pollv()
1649{
1650 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651
Roland McGrathee9d4352002-12-18 04:16:10 +00001652 if (pollv != NULL)
1653 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001654 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001655 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001656 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001657 exit(1);
1658 }
1659
Roland McGrathca16be82003-01-10 19:55:28 +00001660 for (i = j = 0; i < tcbtabsize; i++) {
1661 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662 if (!(tcp->flags & TCB_INUSE))
1663 continue;
1664 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001665 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 j++;
1667 }
1668 if (j != nprocs) {
1669 fprintf(stderr, "strace: proc miscount\n");
1670 exit(1);
1671 }
1672}
1673
1674#ifndef HAVE_POLLABLE_PROCFS
1675
1676static void
1677proc_poll_open()
1678{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679 int i;
1680
1681 if (pipe(proc_poll_pipe) < 0) {
1682 perror("pipe");
1683 exit(1);
1684 }
1685 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001686 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 exit(1);
1688 }
1689 }
1690}
1691
1692static int
1693proc_poll(pollv, nfds, timeout)
1694struct pollfd *pollv;
1695int nfds;
1696int timeout;
1697{
1698 int i;
1699 int n;
1700 struct proc_pollfd pollinfo;
1701
1702 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1703 return n;
1704 if (n != sizeof(struct proc_pollfd)) {
1705 fprintf(stderr, "panic: short read: %d\n", n);
1706 exit(1);
1707 }
1708 for (i = 0; i < nprocs; i++) {
1709 if (pollv[i].fd == pollinfo.fd)
1710 pollv[i].revents = pollinfo.revents;
1711 else
1712 pollv[i].revents = 0;
1713 }
1714 poller_pid = pollinfo.pid;
1715 return 1;
1716}
1717
1718static void
1719wakeup_handler(sig)
1720int sig;
1721{
1722}
1723
1724static void
1725proc_poller(pfd)
1726int pfd;
1727{
1728 struct proc_pollfd pollinfo;
1729 struct sigaction sa;
1730 sigset_t blocked_set, empty_set;
1731 int i;
1732 int n;
1733 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001734#ifdef FREEBSD
1735 struct procfs_status pfs;
1736#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737
1738 switch (fork()) {
1739 case -1:
1740 perror("fork");
1741 _exit(0);
1742 case 0:
1743 break;
1744 default:
1745 return;
1746 }
1747
1748 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1749 sa.sa_flags = 0;
1750 sigemptyset(&sa.sa_mask);
1751 sigaction(SIGHUP, &sa, NULL);
1752 sigaction(SIGINT, &sa, NULL);
1753 sigaction(SIGQUIT, &sa, NULL);
1754 sigaction(SIGPIPE, &sa, NULL);
1755 sigaction(SIGTERM, &sa, NULL);
1756 sa.sa_handler = wakeup_handler;
1757 sigaction(SIGUSR1, &sa, NULL);
1758 sigemptyset(&blocked_set);
1759 sigaddset(&blocked_set, SIGUSR1);
1760 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1761 sigemptyset(&empty_set);
1762
1763 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1764 perror("getrlimit(RLIMIT_NOFILE, ...)");
1765 _exit(0);
1766 }
1767 n = rl.rlim_cur;
1768 for (i = 0; i < n; i++) {
1769 if (i != pfd && i != proc_poll_pipe[1])
1770 close(i);
1771 }
1772
1773 pollinfo.fd = pfd;
1774 pollinfo.pid = getpid();
1775 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001776#ifndef FREEBSD
1777 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1778#else /* FREEBSD */
1779 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1780#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001781 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782 switch (errno) {
1783 case EINTR:
1784 continue;
1785 case EBADF:
1786 pollinfo.revents = POLLERR;
1787 break;
1788 case ENOENT:
1789 pollinfo.revents = POLLHUP;
1790 break;
1791 default:
1792 perror("proc_poller: PIOCWSTOP");
1793 }
1794 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1795 _exit(0);
1796 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001797 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1799 sigsuspend(&empty_set);
1800 }
1801}
1802
1803#endif /* !HAVE_POLLABLE_PROCFS */
1804
1805static int
1806choose_pfd()
1807{
1808 int i, j;
1809 struct tcb *tcp;
1810
1811 static int last;
1812
1813 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001814 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001815 /*
1816 * The previous process is ready to run again. We'll
1817 * let it do so if it is currently in a syscall. This
1818 * heuristic improves the readability of the trace.
1819 */
1820 tcp = pfd2tcb(pollv[last].fd);
1821 if (tcp && (tcp->flags & TCB_INSYSCALL))
1822 return pollv[last].fd;
1823 }
1824
1825 for (i = 0; i < nprocs; i++) {
1826 /* Let competing children run round robin. */
1827 j = (i + last + 1) % nprocs;
1828 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1829 tcp = pfd2tcb(pollv[j].fd);
1830 if (!tcp) {
1831 fprintf(stderr, "strace: lost proc\n");
1832 exit(1);
1833 }
1834 droptcb(tcp);
1835 return -1;
1836 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001837 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 last = j;
1839 return pollv[j].fd;
1840 }
1841 }
1842 fprintf(stderr, "strace: nothing ready\n");
1843 exit(1);
1844}
1845
1846static int
1847trace()
1848{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001849#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001850 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001851#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852 struct tcb *tcp;
1853 int pfd;
1854 int what;
1855 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001856 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857
1858 for (;;) {
1859 if (interactive)
1860 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1861
1862 if (nprocs == 0)
1863 break;
1864
1865 switch (nprocs) {
1866 case 1:
1867#ifndef HAVE_POLLABLE_PROCFS
1868 if (proc_poll_pipe[0] == -1) {
1869#endif
1870 tcp = pid2tcb(0);
1871 if (!tcp)
1872 continue;
1873 pfd = tcp->pfd;
1874 if (pfd == -1)
1875 continue;
1876 break;
1877#ifndef HAVE_POLLABLE_PROCFS
1878 }
1879 /* fall through ... */
1880#endif /* !HAVE_POLLABLE_PROCFS */
1881 default:
1882#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001883#ifdef POLL_HACK
1884 /* On some systems (e.g. UnixWare) we get too much ugly
1885 "unfinished..." stuff when multiple proceses are in
1886 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001887
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001888 if (in_syscall) {
1889 struct pollfd pv;
1890 tcp = in_syscall;
1891 in_syscall = NULL;
1892 pv.fd = tcp->pfd;
1893 pv.events = POLLWANT;
1894 if ((what = poll (&pv, 1, 1)) < 0) {
1895 if (interrupted)
1896 return 0;
1897 continue;
1898 }
1899 else if (what == 1 && pv.revents & POLLWANT) {
1900 goto FOUND;
1901 }
1902 }
1903#endif
1904
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 if (poll(pollv, nprocs, INFTIM) < 0) {
1906 if (interrupted)
1907 return 0;
1908 continue;
1909 }
1910#else /* !HAVE_POLLABLE_PROCFS */
1911 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1912 if (interrupted)
1913 return 0;
1914 continue;
1915 }
1916#endif /* !HAVE_POLLABLE_PROCFS */
1917 pfd = choose_pfd();
1918 if (pfd == -1)
1919 continue;
1920 break;
1921 }
1922
1923 /* Look up `pfd' in our table. */
1924 if ((tcp = pfd2tcb(pfd)) == NULL) {
1925 fprintf(stderr, "unknown pfd: %u\n", pfd);
1926 exit(1);
1927 }
John Hughesb6643082002-05-23 11:02:22 +00001928#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001929 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001930#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931 /* Get the status of the process. */
1932 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001933#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001934 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001935#else /* FREEBSD */
1936 /* Thanks to some scheduling mystery, the first poller
1937 sometimes waits for the already processed end of fork
1938 event. Doing a non blocking poll here solves the problem. */
1939 if (proc_poll_pipe[0] != -1)
1940 ioctl_result = IOCTL_STATUS (tcp);
1941 else
1942 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001943#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001944 ioctl_errno = errno;
1945#ifndef HAVE_POLLABLE_PROCFS
1946 if (proc_poll_pipe[0] != -1) {
1947 if (ioctl_result < 0)
1948 kill(poller_pid, SIGKILL);
1949 else
1950 kill(poller_pid, SIGUSR1);
1951 }
1952#endif /* !HAVE_POLLABLE_PROCFS */
1953 }
1954 if (interrupted)
1955 return 0;
1956
1957 if (interactive)
1958 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1959
1960 if (ioctl_result < 0) {
1961 /* Find out what happened if it failed. */
1962 switch (ioctl_errno) {
1963 case EINTR:
1964 case EBADF:
1965 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001966#ifdef FREEBSD
1967 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001968#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 case ENOENT:
1970 droptcb(tcp);
1971 continue;
1972 default:
1973 perror("PIOCWSTOP");
1974 exit(1);
1975 }
1976 }
1977
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001978#ifdef FREEBSD
1979 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1980 /* discard first event for a syscall we never entered */
1981 IOCTL (tcp->pfd, PIOCRUN, 0);
1982 continue;
1983 }
Roland McGrath553a6092002-12-16 20:40:39 +00001984#endif
1985
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 /* clear the just started flag */
1987 tcp->flags &= ~TCB_STARTUP;
1988
1989 /* set current output file */
1990 outf = tcp->outf;
1991
1992 if (cflag) {
1993 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001994#ifdef FREEBSD
1995 char buf[1024];
1996 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001998 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1999 buf[len] = '\0';
2000 sscanf(buf,
2001 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2002 &stime.tv_sec, &stime.tv_usec);
2003 } else
2004 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002005#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002006 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2007 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002008#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2010 tcp->stime = stime;
2011 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002012 what = tcp->status.PR_WHAT;
2013 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002014#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002016 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2017 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002018 if (trace_syscall(tcp) < 0) {
2019 fprintf(stderr, "syscall trouble\n");
2020 exit(1);
2021 }
2022 }
2023 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002024#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002026#ifdef POLL_HACK
2027 in_syscall = tcp;
2028#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029 case PR_SYSEXIT:
2030 if (trace_syscall(tcp) < 0) {
2031 fprintf(stderr, "syscall trouble\n");
2032 exit(1);
2033 }
2034 break;
2035 case PR_SIGNALLED:
2036 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2037 printleader(tcp);
2038 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002039 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002041#ifdef PR_INFO
2042 if (tcp->status.PR_INFO.si_signo == what) {
2043 printleader(tcp);
2044 tprintf(" siginfo=");
2045 printsiginfo(&tcp->status.PR_INFO, 1);
2046 printtrailer(tcp);
2047 }
2048#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049 }
2050 break;
2051 case PR_FAULTED:
2052 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2053 printleader(tcp);
2054 tprintf("=== FAULT %d ===", what);
2055 printtrailer(tcp);
2056 }
2057 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002058#ifdef FREEBSD
2059 case 0: /* handle case we polled for nothing */
2060 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002061#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002063 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064 exit(1);
2065 break;
2066 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002067 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002068#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002069 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002070#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002071 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002072#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002073 perror("PIOCRUN");
2074 exit(1);
2075 }
2076 }
2077 return 0;
2078}
2079
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002080#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002082#ifdef TCB_GROUP_EXITING
2083/* Handle an exit detach or death signal that is taking all the
2084 related clone threads with it. This is called in three circumstances:
2085 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2086 SIG == 0 Continuing TCP will perform an exit_group syscall.
2087 SIG == other Continuing TCP with SIG will kill the process.
2088*/
2089static int
2090handle_group_exit(struct tcb *tcp, int sig)
2091{
2092 /* We need to locate our records of all the clone threads
2093 related to TCP, either its children or siblings. */
2094 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2095 ? tcp->parent
2096 : tcp->nclone_detached > 0
2097 ? tcp : NULL);
2098
2099 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002100 if (leader != NULL && leader != tcp &&
2101 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002102 fprintf(stderr,
2103 "PANIC: handle_group_exit: %d leader %d\n",
2104 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002105 /* TCP no longer exists therefore you must not detach () it. */
2106 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002107 }
2108 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002109 /* Mark that we are taking the process down. */
2110 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002111 if (tcp->flags & TCB_ATTACHED) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00002112 if (leader != NULL && leader != tcp) {
Roland McGrath0a463882007-07-05 18:43:16 +00002113 if ((leader->flags & TCB_ATTACHED) &&
2114 !(leader->flags & TCB_EXITING)) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00002115 /* We need to detach the leader so
2116 that the process death will be
2117 reported to its real parent.
2118 But we kill it first to prevent
2119 it doing anything before we kill
2120 the whole process in a moment.
2121 We can use PTRACE_KILL on a
2122 thread that's not already
2123 stopped. Then the value we pass
2124 in PTRACE_DETACH just sets the
2125 death signal reported to the
Roland McGrath0a463882007-07-05 18:43:16 +00002126 real parent.
2127 FIXME: This killing gets caught by
2128 WAITPID of the leader's parent.
2129 Testcase: test/leaderkill.c */
Roland McGrath00dc13f2004-10-20 02:04:15 +00002130 ptrace(PTRACE_KILL, leader->pid, 0, 0);
2131 if (debug)
2132 fprintf(stderr,
2133 " [%d exit %d kills %d]\n",
2134 tcp->pid, sig, leader->pid);
2135 detach(leader, sig);
2136 }
2137 else
2138 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002139 }
2140 detach(tcp, sig);
2141 }
2142 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2143 perror("strace: ptrace(PTRACE_CONT, ...)");
2144 cleanup();
2145 return -1;
2146 }
2147 else {
Roland McGrath05690952004-10-20 01:00:27 +00002148 if (leader != NULL)
2149 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002150 if (leader != NULL && leader != tcp)
2151 droptcb(tcp);
2152 /* The leader will report to us as parent now,
2153 and then we'll get to the SIG==-1 case. */
2154 return 0;
2155 }
2156 }
2157
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002158 return 0;
2159}
2160#endif
2161
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002162static int
2163trace()
2164{
2165 int pid;
2166 int wait_errno;
2167 int status;
2168 struct tcb *tcp;
2169#ifdef LINUX
2170 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002171#ifdef __WALL
2172 static int wait4_options = __WALL;
2173#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002174#endif /* LINUX */
2175
2176 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002177 if (interrupted)
2178 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002179 if (interactive)
2180 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2181#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002182#ifdef __WALL
2183 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002184 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002185 /* this kernel does not support __WALL */
2186 wait4_options &= ~__WALL;
2187 errno = 0;
2188 pid = wait4(-1, &status, wait4_options,
2189 cflag ? &ru : NULL);
2190 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002191 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002192 /* most likely a "cloned" process */
2193 pid = wait4(-1, &status, __WCLONE,
2194 cflag ? &ru : NULL);
2195 if (pid == -1) {
2196 fprintf(stderr, "strace: clone wait4 "
2197 "failed: %s\n", strerror(errno));
2198 }
2199 }
2200#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002202#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203#endif /* LINUX */
2204#ifdef SUNOS4
2205 pid = wait(&status);
2206#endif /* SUNOS4 */
2207 wait_errno = errno;
2208 if (interactive)
2209 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2210
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 if (pid == -1) {
2212 switch (wait_errno) {
2213 case EINTR:
2214 continue;
2215 case ECHILD:
2216 /*
2217 * We would like to verify this case
2218 * but sometimes a race in Solbourne's
2219 * version of SunOS sometimes reports
2220 * ECHILD before sending us SIGCHILD.
2221 */
2222#if 0
2223 if (nprocs == 0)
2224 return 0;
2225 fprintf(stderr, "strace: proc miscount\n");
2226 exit(1);
2227#endif
2228 return 0;
2229 default:
2230 errno = wait_errno;
2231 perror("strace: wait");
2232 return -1;
2233 }
2234 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002235 if (pid == popen_pid) {
2236 if (WIFEXITED(status) || WIFSIGNALED(status))
2237 popen_pid = -1;
2238 continue;
2239 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002240 if (debug)
2241 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2242
2243 /* Look up `pid' in our table. */
2244 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002245#ifdef LINUX
2246 if (followfork || followvfork) {
2247 /* This is needed to go with the CLONE_PTRACE
2248 changes in process.c/util.c: we might see
2249 the child's initial trap before we see the
2250 parent return from the clone syscall.
2251 Leave the child suspended until the parent
2252 returns from its system call. Only then
2253 will we have the association of parent and
2254 child so that we know how to do clearbpt
2255 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002256 if (nprocs == tcbtabsize &&
2257 expand_tcbtab())
2258 tcp = NULL;
2259 else
2260 tcp = alloctcb(pid);
2261 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002262 kill(pid, SIGKILL); /* XXX */
2263 return 0;
2264 }
2265 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002266 if (!qflag)
2267 fprintf(stderr, "\
2268Process %d attached (waiting for parent)\n",
2269 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002270 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002271 else
2272 /* This can happen if a clone call used
2273 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002274#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002275 {
2276 fprintf(stderr, "unknown pid: %u\n", pid);
2277 if (WIFSTOPPED(status))
2278 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2279 exit(1);
2280 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002281 }
2282 /* set current output file */
2283 outf = tcp->outf;
2284 if (cflag) {
2285#ifdef LINUX
2286 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2287 tcp->stime = ru.ru_stime;
2288#endif /* !LINUX */
2289 }
2290
2291 if (tcp->flags & TCB_SUSPENDED) {
2292 /*
2293 * Apparently, doing any ptrace() call on a stopped
2294 * process, provokes the kernel to report the process
2295 * status again on a subsequent wait(), even if the
2296 * process has not been actually restarted.
2297 * Since we have inspected the arguments of suspended
2298 * processes we end up here testing for this case.
2299 */
2300 continue;
2301 }
2302 if (WIFSIGNALED(status)) {
2303 if (!cflag
2304 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2305 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002306 tprintf("+++ killed by %s %s+++",
2307 signame(WTERMSIG(status)),
2308#ifdef WCOREDUMP
2309 WCOREDUMP(status) ? "(core dumped) " :
2310#endif
2311 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312 printtrailer(tcp);
2313 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002314#ifdef TCB_GROUP_EXITING
2315 handle_group_exit(tcp, -1);
2316#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002318#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002319 continue;
2320 }
2321 if (WIFEXITED(status)) {
2322 if (debug)
2323 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002324 if ((tcp->flags & TCB_ATTACHED)
2325#ifdef TCB_GROUP_EXITING
2326 && !(tcp->parent && (tcp->parent->flags &
2327 TCB_GROUP_EXITING))
2328#endif
2329 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 fprintf(stderr,
2331 "PANIC: attached pid %u exited\n",
2332 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002333 if (tcp == tcp_last) {
2334 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2335 == TCB_INSYSCALL)
2336 tprintf(" <unfinished ... exit status %d>\n",
2337 WEXITSTATUS(status));
2338 tcp_last = NULL;
2339 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002340#ifdef TCB_GROUP_EXITING
2341 handle_group_exit(tcp, -1);
2342#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002344#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 continue;
2346 }
2347 if (!WIFSTOPPED(status)) {
2348 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2349 droptcb(tcp);
2350 continue;
2351 }
2352 if (debug)
2353 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002354 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002355
Roland McGrath02203312007-06-11 22:06:31 +00002356 /*
2357 * Interestingly, the process may stop
2358 * with STOPSIG equal to some other signal
2359 * than SIGSTOP if we happend to attach
2360 * just before the process takes a signal.
2361 */
2362 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363 /*
2364 * This flag is there to keep us in sync.
2365 * Next time this process stops it should
2366 * really be entering a system call.
2367 */
2368 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002369 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002370 /*
2371 * One example is a breakpoint inherited from
2372 * parent through fork ().
2373 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2375 droptcb(tcp);
2376 cleanup();
2377 return -1;
2378 }
2379 }
2380 goto tracing;
2381 }
2382
2383 if (WSTOPSIG(status) != SIGTRAP) {
2384 if (WSTOPSIG(status) == SIGSTOP &&
2385 (tcp->flags & TCB_SIGTRAPPED)) {
2386 /*
2387 * Trapped attempt to block SIGTRAP
2388 * Hope we are back in control now.
2389 */
2390 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2391 if (ptrace(PTRACE_SYSCALL,
2392 pid, (char *) 1, 0) < 0) {
2393 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2394 cleanup();
2395 return -1;
2396 }
2397 continue;
2398 }
2399 if (!cflag
2400 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002401 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002402#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002403# define PSR_RI 41
2404 struct siginfo si;
2405 unsigned long psr;
2406
2407 upeek(pid, PT_CR_IPSR, &psr);
2408 upeek(pid, PT_CR_IIP, &pc);
2409
2410 pc += (psr >> PSR_RI) & 0x3;
2411 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2412 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002413#elif defined PTRACE_GETSIGINFO
2414 if (WSTOPSIG(status) == SIGSEGV ||
2415 WSTOPSIG(status) == SIGBUS) {
2416 siginfo_t si;
2417 if (ptrace(PTRACE_GETSIGINFO, pid,
2418 0, &si) == 0)
2419 addr = (unsigned long)
2420 si.si_addr;
2421 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002422#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002423 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002424 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002425 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002426 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002427 printtrailer(tcp);
2428 }
Roland McGrath05690952004-10-20 01:00:27 +00002429 if (((tcp->flags & TCB_ATTACHED) ||
2430 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002431 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002432#ifdef TCB_GROUP_EXITING
2433 handle_group_exit(tcp, WSTOPSIG(status));
2434#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002435 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002436#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002437 continue;
2438 }
2439 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2440 WSTOPSIG(status)) < 0) {
2441 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2442 cleanup();
2443 return -1;
2444 }
2445 tcp->flags &= ~TCB_SUSPENDED;
2446 continue;
2447 }
Roland McGrath02203312007-06-11 22:06:31 +00002448 /* we handled the STATUS, we are permitted to interrupt now. */
2449 if (interrupted)
2450 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002451 if (trace_syscall(tcp) < 0) {
2452 if (tcp->flags & TCB_ATTACHED)
2453 detach(tcp, 0);
2454 else {
2455 ptrace(PTRACE_KILL,
2456 tcp->pid, (char *) 1, SIGTERM);
2457 droptcb(tcp);
2458 }
2459 continue;
2460 }
2461 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002462#ifdef TCB_GROUP_EXITING
2463 if (tcp->flags & TCB_GROUP_EXITING) {
2464 if (handle_group_exit(tcp, 0) < 0)
2465 return -1;
2466 continue;
2467 }
2468#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002469 if (tcp->flags & TCB_ATTACHED)
2470 detach(tcp, 0);
2471 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2472 perror("strace: ptrace(PTRACE_CONT, ...)");
2473 cleanup();
2474 return -1;
2475 }
2476 continue;
2477 }
2478 if (tcp->flags & TCB_SUSPENDED) {
2479 if (!qflag)
2480 fprintf(stderr, "Process %u suspended\n", pid);
2481 continue;
2482 }
2483 tracing:
2484 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2485 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2486 cleanup();
2487 return -1;
2488 }
2489 }
2490 return 0;
2491}
2492
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002493#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002494
2495static int curcol;
2496
2497#ifdef __STDC__
2498#include <stdarg.h>
2499#define VA_START(a, b) va_start(a, b)
2500#else
2501#include <varargs.h>
2502#define VA_START(a, b) va_start(a)
2503#endif
2504
2505void
2506#ifdef __STDC__
2507tprintf(const char *fmt, ...)
2508#else
2509tprintf(fmt, va_alist)
2510char *fmt;
2511va_dcl
2512#endif
2513{
2514 va_list args;
2515
2516 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002517 if (outf) {
2518 int n = vfprintf(outf, fmt, args);
2519 if (n < 0 && outf != stderr)
2520 perror(outfname == NULL
2521 ? "<writing to pipe>" : outfname);
2522 else
2523 curcol += n;
2524 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 va_end(args);
2526 return;
2527}
2528
2529void
2530printleader(tcp)
2531struct tcb *tcp;
2532{
2533 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2534 tcp_last->flags |= TCB_REPRINT;
2535 tprintf(" <unfinished ...>\n");
2536 }
2537 curcol = 0;
2538 if ((followfork == 1 || pflag_seen > 1) && outfname)
2539 tprintf("%-5d ", tcp->pid);
2540 else if (nprocs > 1 && !outfname)
2541 tprintf("[pid %5u] ", tcp->pid);
2542 if (tflag) {
2543 char str[sizeof("HH:MM:SS")];
2544 struct timeval tv, dtv;
2545 static struct timeval otv;
2546
2547 gettimeofday(&tv, NULL);
2548 if (rflag) {
2549 if (otv.tv_sec == 0)
2550 otv = tv;
2551 tv_sub(&dtv, &tv, &otv);
2552 tprintf("%6ld.%06ld ",
2553 (long) dtv.tv_sec, (long) dtv.tv_usec);
2554 otv = tv;
2555 }
2556 else if (tflag > 2) {
2557 tprintf("%ld.%06ld ",
2558 (long) tv.tv_sec, (long) tv.tv_usec);
2559 }
2560 else {
2561 time_t local = tv.tv_sec;
2562 strftime(str, sizeof(str), "%T", localtime(&local));
2563 if (tflag > 1)
2564 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2565 else
2566 tprintf("%s ", str);
2567 }
2568 }
2569 if (iflag)
2570 printcall(tcp);
2571}
2572
2573void
2574tabto(col)
2575int col;
2576{
2577 if (curcol < col)
2578 tprintf("%*s", col - curcol, "");
2579}
2580
2581void
2582printtrailer(tcp)
2583struct tcb *tcp;
2584{
2585 tprintf("\n");
2586 tcp_last = NULL;
2587}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002588
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002589#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002590
2591int mp_ioctl (int fd, int cmd, void *arg, int size) {
2592
2593 struct iovec iov[2];
2594 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002595
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002596 iov[0].iov_base = &cmd;
2597 iov[0].iov_len = sizeof cmd;
2598 if (arg) {
2599 ++n;
2600 iov[1].iov_base = arg;
2601 iov[1].iov_len = size;
2602 }
Roland McGrath553a6092002-12-16 20:40:39 +00002603
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002604 return writev (fd, iov, n);
2605}
2606
2607#endif