blob: 8a77bb14ba73d8f1e0b075e270e3c7956db4a921 [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;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000625 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000626 struct sigaction sa;
627
628 static char buf[BUFSIZ];
629
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000630 progname = argv[0] ? argv[0] : "strace";
631
Roland McGrathee9d4352002-12-18 04:16:10 +0000632 /* Allocate the initial tcbtab. */
633 tcbtabsize = argc; /* Surely enough for all -p args. */
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000634 if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) {
635 fprintf(stderr, "%s: out of memory\n", progname);
636 exit(1);
637 }
638 if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
639 fprintf(stderr, "%s: out of memory\n", progname);
640 exit(1);
641 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000642 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
643 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
644
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000645 outf = stderr;
646 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000647 set_sortby(DEFAULT_SORTBY);
648 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649 qualify("trace=all");
650 qualify("abbrev=all");
651 qualify("verbose=all");
652 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000654 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655 switch (c) {
656 case 'c':
657 cflag++;
658 dtime++;
659 break;
660 case 'd':
661 debug++;
662 break;
Roland McGrath41c48222008-07-18 00:25:10 +0000663 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000664 optF = 1;
665 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 case 'f':
667 followfork++;
668 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000669 case 'h':
670 usage(stdout, 0);
671 break;
672 case 'i':
673 iflag++;
674 break;
675 case 'q':
676 qflag++;
677 break;
678 case 'r':
679 rflag++;
680 tflag++;
681 break;
682 case 't':
683 tflag++;
684 break;
685 case 'T':
686 dtime++;
687 break;
688 case 'x':
689 xflag++;
690 break;
691 case 'v':
692 qualify("abbrev=none");
693 break;
694 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000695 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696 exit(0);
697 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000698 case 'z':
699 not_failing_only = 1;
700 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000701 case 'a':
702 acolumn = atoi(optarg);
703 break;
704 case 'e':
705 qualify(optarg);
706 break;
707 case 'o':
708 outfname = strdup(optarg);
709 break;
710 case 'O':
711 set_overhead(atoi(optarg));
712 break;
713 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000714 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 fprintf(stderr, "%s: Invalid process id: %s\n",
716 progname, optarg);
717 break;
718 }
719 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000720 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721 break;
722 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000723 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000724 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000725 progname);
726 exit(1);
727 }
728 tcp->flags |= TCB_ATTACHED;
729 pflag_seen++;
730 break;
731 case 's':
732 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000733 if (max_strlen < 0) {
734 fprintf(stderr,
735 "%s: invalid -s argument: %s\n",
736 progname, optarg);
737 exit(1);
738 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000739 break;
740 case 'S':
741 set_sortby(optarg);
742 break;
743 case 'u':
744 username = strdup(optarg);
745 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000746 case 'E':
747 if (putenv(optarg) < 0) {
748 fprintf(stderr, "%s: out of memory\n",
749 progname);
750 exit(1);
751 }
752 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000753 default:
754 usage(stderr, 1);
755 break;
756 }
757 }
758
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000759 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000760 usage(stderr, 1);
761
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000762 if (!followfork)
763 followfork = optF;
764
Roland McGrathcb9def62006-04-25 07:48:03 +0000765 if (followfork > 1 && cflag) {
766 fprintf(stderr,
767 "%s: -c and -ff are mutually exclusive options\n",
768 progname);
769 exit(1);
770 }
771
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000772 /* See if they want to run as another user. */
773 if (username != NULL) {
774 struct passwd *pent;
775
776 if (getuid() != 0 || geteuid() != 0) {
777 fprintf(stderr,
778 "%s: you must be root to use the -u option\n",
779 progname);
780 exit(1);
781 }
782 if ((pent = getpwnam(username)) == NULL) {
783 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000784 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785 exit(1);
786 }
787 run_uid = pent->pw_uid;
788 run_gid = pent->pw_gid;
789 }
790 else {
791 run_uid = getuid();
792 run_gid = getgid();
793 }
794
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000795 /* Check if they want to redirect the output. */
796 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000797 /* See if they want to pipe the output. */
798 if (outfname[0] == '|' || outfname[0] == '!') {
799 /*
800 * We can't do the <outfname>.PID funny business
801 * when using popen, so prohibit it.
802 */
803 if (followfork > 1) {
804 fprintf(stderr, "\
805%s: piping the output and -ff are mutually exclusive options\n",
806 progname);
807 exit(1);
808 }
809
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000810 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000811 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000812 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000813 else if (followfork <= 1 &&
814 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000815 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 }
817
Roland McGrath37b9a662003-11-07 02:26:54 +0000818 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000820 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000822 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000823 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000824 /* Valid states here:
825 optind < argc pflag_seen outfname interactive
826 1 0 0 1
827 0 1 0 1
828 1 0 1 0
829 0 1 1 1
830 */
831
832 /* STARTUP_CHILD must be called before the signal handlers get
833 installed below as they are inherited into the spawned process.
834 Also we do not need to be protected by them as during interruption
835 in the STARTUP_CHILD mode we kill the spawned process anyway. */
836 if (!pflag_seen)
837 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000838
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000839 sigemptyset(&empty_set);
840 sigemptyset(&blocked_set);
841 sa.sa_handler = SIG_IGN;
842 sigemptyset(&sa.sa_mask);
843 sa.sa_flags = 0;
844 sigaction(SIGTTOU, &sa, NULL);
845 sigaction(SIGTTIN, &sa, NULL);
846 if (interactive) {
847 sigaddset(&blocked_set, SIGHUP);
848 sigaddset(&blocked_set, SIGINT);
849 sigaddset(&blocked_set, SIGQUIT);
850 sigaddset(&blocked_set, SIGPIPE);
851 sigaddset(&blocked_set, SIGTERM);
852 sa.sa_handler = interrupt;
853#ifdef SUNOS4
854 /* POSIX signals on sunos4.1 are a little broken. */
855 sa.sa_flags = SA_INTERRUPT;
856#endif /* SUNOS4 */
857 }
858 sigaction(SIGHUP, &sa, NULL);
859 sigaction(SIGINT, &sa, NULL);
860 sigaction(SIGQUIT, &sa, NULL);
861 sigaction(SIGPIPE, &sa, NULL);
862 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000863#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864 sa.sa_handler = reaper;
865 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000866#else
867 /* Make sure SIGCHLD has the default action so that waitpid
868 definitely works without losing track of children. The user
869 should not have given us a bogus state to inherit, but he might
870 have. Arguably we should detect SIG_IGN here and pass it on
871 to children, but probably noone really needs that. */
872 sa.sa_handler = SIG_DFL;
873 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000874#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000875
Roland McGrath02203312007-06-11 22:06:31 +0000876 if (pflag_seen)
877 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000878
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879 if (trace() < 0)
880 exit(1);
881 cleanup();
882 exit(0);
883}
884
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000885int
886expand_tcbtab()
887{
888 /* Allocate some more TCBs and expand the table.
889 We don't want to relocate the TCBs because our
890 callers have pointers and it would be a pain.
891 So tcbtab is a table of pointers. Since we never
892 free the TCBs, we allocate a single chunk of many. */
893 struct tcb **newtab = (struct tcb **)
894 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
895 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
896 sizeof *newtcbs);
897 int i;
898 if (newtab == NULL || newtcbs == NULL) {
899 if (newtab != NULL)
900 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000901 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
902 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000903 return 1;
904 }
905 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
906 newtab[i] = &newtcbs[i - tcbtabsize];
907 tcbtabsize *= 2;
908 tcbtab = newtab;
909
910 return 0;
911}
912
913
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000915alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916{
917 int i;
918 struct tcb *tcp;
919
Roland McGrathee9d4352002-12-18 04:16:10 +0000920 for (i = 0; i < tcbtabsize; i++) {
921 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 if ((tcp->flags & TCB_INUSE) == 0) {
923 tcp->pid = pid;
924 tcp->parent = NULL;
925 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000926 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000927#ifdef TCB_CLONE_THREAD
928 tcp->nclone_threads = tcp->nclone_detached = 0;
929 tcp->nclone_waiting = 0;
930#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 tcp->flags = TCB_INUSE | TCB_STARTUP;
932 tcp->outf = outf; /* Initialise to current out file */
933 tcp->stime.tv_sec = 0;
934 tcp->stime.tv_usec = 0;
935 tcp->pfd = -1;
936 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000937 if (command_options_parsed)
938 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 return tcp;
940 }
941 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000942 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000943 return NULL;
944}
945
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000946#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947int
948proc_open(tcp, attaching)
949struct tcb *tcp;
950int attaching;
951{
952 char proc[32];
953 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000954#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000955 int i;
956 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 sigset_t signals;
958 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000959#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000960#ifndef HAVE_POLLABLE_PROCFS
961 static int last_pfd;
962#endif
963
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000964#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000965 /* Open the process pseudo-files in /proc. */
966 sprintf(proc, "/proc/%d/ctl", tcp->pid);
967 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 perror("strace: open(\"/proc/...\", ...)");
969 return -1;
970 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000971 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 return -1;
973 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000974 sprintf(proc, "/proc/%d/status", tcp->pid);
975 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
976 perror("strace: open(\"/proc/...\", ...)");
977 return -1;
978 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000979 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000980 return -1;
981 }
982 sprintf(proc, "/proc/%d/as", tcp->pid);
983 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
984 perror("strace: open(\"/proc/...\", ...)");
985 return -1;
986 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000987 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000988 return -1;
989 }
990#else
991 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000992#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000993 sprintf(proc, "/proc/%d", tcp->pid);
994 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000995#else /* FREEBSD */
996 sprintf(proc, "/proc/%d/mem", tcp->pid);
997 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
998#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000999 perror("strace: open(\"/proc/...\", ...)");
1000 return -1;
1001 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001002 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001003 return -1;
1004 }
1005#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001006#ifdef FREEBSD
1007 sprintf(proc, "/proc/%d/regs", tcp->pid);
1008 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1009 perror("strace: open(\"/proc/.../regs\", ...)");
1010 return -1;
1011 }
1012 if (cflag) {
1013 sprintf(proc, "/proc/%d/status", tcp->pid);
1014 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1015 perror("strace: open(\"/proc/.../status\", ...)");
1016 return -1;
1017 }
1018 } else
1019 tcp->pfd_status = -1;
1020#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001021 rebuild_pollv();
1022 if (!attaching) {
1023 /*
1024 * Wait for the child to pause. Because of a race
1025 * condition we have to poll for the event.
1026 */
1027 for (;;) {
1028 if (IOCTL_STATUS (tcp) < 0) {
1029 perror("strace: PIOCSTATUS");
1030 return -1;
1031 }
1032 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001033 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001034 }
1035 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001036#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001037 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001038 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001039 perror("strace: PIOCSTOP");
1040 return -1;
1041 }
Roland McGrath553a6092002-12-16 20:40:39 +00001042#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043#ifdef PIOCSET
1044 /* Set Run-on-Last-Close. */
1045 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001046 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 perror("PIOCSET PR_RLC");
1048 return -1;
1049 }
1050 /* Set or Reset Inherit-on-Fork. */
1051 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001052 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 perror("PIOC{SET,RESET} PR_FORK");
1054 return -1;
1055 }
1056#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001057#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1059 perror("PIOCSRLC");
1060 return -1;
1061 }
1062 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1063 perror("PIOC{S,R}FORK");
1064 return -1;
1065 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001066#else /* FREEBSD */
1067 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1068 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1069 perror("PIOCGFL");
1070 return -1;
1071 }
1072 arg &= ~PF_LINGER;
1073 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1074 perror("PIOCSFL");
1075 return -1;
1076 }
1077#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001079#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001080 /* Enable all syscall entries we care about. */
1081 premptyset(&syscalls);
1082 for (i = 1; i < MAX_QUALS; ++i) {
1083 if (i > (sizeof syscalls) * CHAR_BIT) break;
1084 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1085 }
1086 praddset (&syscalls, SYS_execve);
1087 if (followfork) {
1088 praddset (&syscalls, SYS_fork);
1089#ifdef SYS_forkall
1090 praddset (&syscalls, SYS_forkall);
1091#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001092#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001093 praddset (&syscalls, SYS_fork1);
1094#endif
1095#ifdef SYS_rfork1
1096 praddset (&syscalls, SYS_rfork1);
1097#endif
1098#ifdef SYS_rforkall
1099 praddset (&syscalls, SYS_rforkall);
1100#endif
1101 }
1102 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103 perror("PIOCSENTRY");
1104 return -1;
1105 }
John Hughes19e49982001-10-19 08:59:12 +00001106 /* Enable the syscall exits. */
1107 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 perror("PIOSEXIT");
1109 return -1;
1110 }
John Hughes19e49982001-10-19 08:59:12 +00001111 /* Enable signals we care about. */
1112 premptyset(&signals);
1113 for (i = 1; i < MAX_QUALS; ++i) {
1114 if (i > (sizeof signals) * CHAR_BIT) break;
1115 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1116 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001117 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 perror("PIOCSTRACE");
1119 return -1;
1120 }
John Hughes19e49982001-10-19 08:59:12 +00001121 /* Enable faults we care about */
1122 premptyset(&faults);
1123 for (i = 1; i < MAX_QUALS; ++i) {
1124 if (i > (sizeof faults) * CHAR_BIT) break;
1125 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1126 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001127 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 perror("PIOCSFAULT");
1129 return -1;
1130 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001131#else /* FREEBSD */
1132 /* set events flags. */
1133 arg = S_SIG | S_SCE | S_SCX ;
1134 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1135 perror("PIOCBIS");
1136 return -1;
1137 }
1138#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 if (!attaching) {
1140#ifdef MIPS
1141 /*
1142 * The SGI PRSABORT doesn't work for pause() so
1143 * we send it a caught signal to wake it up.
1144 */
1145 kill(tcp->pid, SIGINT);
1146#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001147#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001149 arg = PRSABORT;
1150 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 perror("PIOCRUN");
1152 return -1;
1153 }
Roland McGrath553a6092002-12-16 20:40:39 +00001154#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001155#endif /* !MIPS*/
1156#ifdef FREEBSD
1157 /* wake up the child if it received the SIGSTOP */
1158 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001159#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160 for (;;) {
1161 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001162 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 perror("PIOCWSTOP");
1164 return -1;
1165 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001166 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001167 tcp->flags &= ~TCB_INSYSCALL;
1168 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001169 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 break;
1171 }
1172 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001173#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001174 arg = 0;
1175 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001176#else /* FREEBSD */
1177 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001178#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179 perror("PIOCRUN");
1180 return -1;
1181 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001182#ifdef FREEBSD
1183 /* handle the case where we "opened" the child before
1184 it did the kill -STOP */
1185 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1186 tcp->status.PR_WHAT == SIGSTOP)
1187 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001188#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001190#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001192#else /* FREEBSD */
1193 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001194 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001195 /* We are attaching to an already running process.
1196 * Try to figure out the state of the process in syscalls,
1197 * to handle the first event well.
1198 * This is done by having a look at the "wchan" property of the
1199 * process, which tells where it is stopped (if it is). */
1200 FILE * status;
1201 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001202
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001203 sprintf(proc, "/proc/%d/status", tcp->pid);
1204 status = fopen(proc, "r");
1205 if (status &&
1206 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1207 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1208 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1209 strcmp(wchan, "stopevent")) {
1210 /* The process is asleep in the middle of a syscall.
1211 Fake the syscall entry event */
1212 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1213 tcp->status.PR_WHY = PR_SYSENTRY;
1214 trace_syscall(tcp);
1215 }
1216 if (status)
1217 fclose(status);
1218 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001219 }
1220#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221#ifndef HAVE_POLLABLE_PROCFS
1222 if (proc_poll_pipe[0] != -1)
1223 proc_poller(tcp->pfd);
1224 else if (nprocs > 1) {
1225 proc_poll_open();
1226 proc_poller(last_pfd);
1227 proc_poller(tcp->pfd);
1228 }
1229 last_pfd = tcp->pfd;
1230#endif /* !HAVE_POLLABLE_PROCFS */
1231 return 0;
1232}
1233
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001234#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001236struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237pid2tcb(pid)
1238int pid;
1239{
1240 int i;
1241 struct tcb *tcp;
1242
Roland McGrathee9d4352002-12-18 04:16:10 +00001243 for (i = 0; i < tcbtabsize; i++) {
1244 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 if (pid && tcp->pid != pid)
1246 continue;
1247 if (tcp->flags & TCB_INUSE)
1248 return tcp;
1249 }
1250 return NULL;
1251}
1252
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001253#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254
1255static struct tcb *
1256pfd2tcb(pfd)
1257int pfd;
1258{
1259 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260
Roland McGrathca16be82003-01-10 19:55:28 +00001261 for (i = 0; i < tcbtabsize; i++) {
1262 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263 if (tcp->pfd != pfd)
1264 continue;
1265 if (tcp->flags & TCB_INUSE)
1266 return tcp;
1267 }
1268 return NULL;
1269}
1270
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001271#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272
1273void
1274droptcb(tcp)
1275struct tcb *tcp;
1276{
1277 if (tcp->pid == 0)
1278 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001279#ifdef TCB_CLONE_THREAD
1280 if (tcp->nclone_threads > 0) {
1281 /* There are other threads left in this process, but this
1282 is the one whose PID represents the whole process.
1283 We need to keep this record around as a zombie until
1284 all the threads die. */
1285 tcp->flags |= TCB_EXITING;
1286 return;
1287 }
1288#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289 nprocs--;
1290 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001291
Roland McGrathe29341c2003-01-10 20:14:20 +00001292 if (tcp->parent != NULL) {
1293 tcp->parent->nchildren--;
1294#ifdef TCB_CLONE_THREAD
1295 if (tcp->flags & TCB_CLONE_DETACHED)
1296 tcp->parent->nclone_detached--;
1297 if (tcp->flags & TCB_CLONE_THREAD)
1298 tcp->parent->nclone_threads--;
1299#endif
Roland McGrath09623452003-05-23 02:27:13 +00001300#ifdef TCB_CLONE_DETACHED
1301 if (!(tcp->flags & TCB_CLONE_DETACHED))
1302#endif
1303 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001304#ifdef LINUX
1305 /* Update `tcp->parent->parent->nchildren' and the other fields
1306 like NCLONE_DETACHED, only for zombie group leader that has
1307 already reported and been short-circuited at the top of this
1308 function. The same condition as at the top of DETACH. */
1309 if ((tcp->flags & TCB_CLONE_THREAD) &&
1310 tcp->parent->nclone_threads == 0 &&
1311 (tcp->parent->flags & TCB_EXITING))
1312 droptcb(tcp->parent);
1313#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001314 tcp->parent = NULL;
1315 }
1316
1317 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318 if (tcp->pfd != -1) {
1319 close(tcp->pfd);
1320 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001321#ifdef FREEBSD
1322 if (tcp->pfd_reg != -1) {
1323 close(tcp->pfd_reg);
1324 tcp->pfd_reg = -1;
1325 }
1326 if (tcp->pfd_status != -1) {
1327 close(tcp->pfd_status);
1328 tcp->pfd_status = -1;
1329 }
Roland McGrath553a6092002-12-16 20:40:39 +00001330#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001331#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001332 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333#endif
1334 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001335
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001336 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001338
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339 tcp->outf = 0;
1340}
1341
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001342#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001343
1344static int
1345resume(tcp)
1346struct tcb *tcp;
1347{
1348 if (tcp == NULL)
1349 return -1;
1350
1351 if (!(tcp->flags & TCB_SUSPENDED)) {
1352 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1353 return -1;
1354 }
1355 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001356#ifdef TCB_CLONE_THREAD
1357 if (tcp->flags & TCB_CLONE_THREAD)
1358 tcp->parent->nclone_waiting--;
1359#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360
1361 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1362 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1363 return -1;
1364 }
1365
1366 if (!qflag)
1367 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1368 return 0;
1369}
1370
Roland McGrath1bfd3102007-08-03 10:02:00 +00001371static int
1372resume_from_tcp (struct tcb *tcp)
1373{
1374 int error = 0;
1375 int resumed = 0;
1376
1377 /* XXX This won't always be quite right (but it never was).
1378 A waiter with argument 0 or < -1 is waiting for any pid in
1379 a particular pgrp, which this child might or might not be
1380 in. The waiter will only wake up if it's argument is -1
1381 or if it's waiting for tcp->pid's pgrp. It makes a
1382 difference to wake up a waiter when there might be more
1383 traced children, because it could get a false ECHILD
1384 error. OTOH, if this was the last child in the pgrp, then
1385 it ought to wake up and get ECHILD. We would have to
1386 search the system for all pid's in the pgrp to be sure.
1387
1388 && (t->waitpid == -1 ||
1389 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1390 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1391 */
1392
1393 if (tcp->parent &&
1394 (tcp->parent->flags & TCB_SUSPENDED) &&
1395 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1396 error = resume(tcp->parent);
1397 ++resumed;
1398 }
1399#ifdef TCB_CLONE_THREAD
1400 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1401 /* Some other threads of our parent are waiting too. */
1402 unsigned int i;
1403
1404 /* Resume all the threads that were waiting for this PID. */
1405 for (i = 0; i < tcbtabsize; i++) {
1406 struct tcb *t = tcbtab[i];
1407 if (t->parent == tcp->parent && t != tcp
1408 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1409 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1410 && t->waitpid == tcp->pid) {
1411 error |= resume (t);
1412 ++resumed;
1413 }
1414 }
1415 if (resumed == 0)
1416 /* Noone was waiting for this PID in particular,
1417 so now we might need to resume some wildcarders. */
1418 for (i = 0; i < tcbtabsize; i++) {
1419 struct tcb *t = tcbtab[i];
1420 if (t->parent == tcp->parent && t != tcp
1421 && ((t->flags
1422 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1423 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1424 && t->waitpid <= 0
1425 ) {
1426 error |= resume (t);
1427 break;
1428 }
1429 }
1430 }
1431
1432 return error;
1433}
1434#endif
1435
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001436#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437
Roland McGrath0a463882007-07-05 18:43:16 +00001438/* detach traced process; continue with sig
1439 Never call DETACH twice on the same process as both unattached and
1440 attached-unstopped processes give the same ESRCH. For unattached process we
1441 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442
1443static int
1444detach(tcp, sig)
1445struct tcb *tcp;
1446int sig;
1447{
1448 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001449#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001450 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001451 struct tcb *zombie = NULL;
1452
1453 /* If the group leader is lingering only because of this other
1454 thread now dying, then detach the leader as well. */
1455 if ((tcp->flags & TCB_CLONE_THREAD) &&
1456 tcp->parent->nclone_threads == 1 &&
1457 (tcp->parent->flags & TCB_EXITING))
1458 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001459#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460
1461 if (tcp->flags & TCB_BPTSET)
1462 sig = SIGKILL;
1463
1464#ifdef LINUX
1465 /*
1466 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001467 * before detaching. Arghh. We go through hoops
1468 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001470#if defined(SPARC)
1471#undef PTRACE_DETACH
1472#define PTRACE_DETACH PTRACE_SUNDETACH
1473#endif
Roland McGrath02203312007-06-11 22:06:31 +00001474 /*
1475 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1476 * expected SIGSTOP. We must catch exactly one as otherwise the
1477 * detached process would be left stopped (process state T).
1478 */
1479 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1481 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001482 }
1483 else if (errno != ESRCH) {
1484 /* Shouldn't happen. */
1485 perror("detach: ptrace(PTRACE_DETACH, ...)");
1486 }
Roland McGrath134813a2007-06-02 00:07:33 +00001487 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1488 : tcp->pid),
1489 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001490 if (errno != ESRCH)
1491 perror("detach: checking sanity");
1492 }
Roland McGrath02203312007-06-11 22:06:31 +00001493 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1494 ? tcp->parent->pid : tcp->pid),
1495 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001496 if (errno != ESRCH)
1497 perror("detach: stopping child");
1498 }
Roland McGrath02203312007-06-11 22:06:31 +00001499 else
1500 catch_sigstop = 1;
1501 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001503#ifdef __WALL
1504 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1505 if (errno == ECHILD) /* Already gone. */
1506 break;
1507 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001508 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001509 break;
1510 }
1511#endif /* __WALL */
1512 /* No __WALL here. */
1513 if (waitpid(tcp->pid, &status, 0) < 0) {
1514 if (errno != ECHILD) {
1515 perror("detach: waiting");
1516 break;
1517 }
1518#ifdef __WCLONE
1519 /* If no processes, try clones. */
1520 if (wait4(tcp->pid, &status, __WCLONE,
1521 NULL) < 0) {
1522 if (errno != ECHILD)
1523 perror("detach: waiting");
1524 break;
1525 }
1526#endif /* __WCLONE */
1527 }
1528#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001529 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001530#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531 if (!WIFSTOPPED(status)) {
1532 /* Au revoir, mon ami. */
1533 break;
1534 }
1535 if (WSTOPSIG(status) == SIGSTOP) {
1536 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001537 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538 if (errno != ESRCH)
1539 perror("detach: ptrace(PTRACE_DETACH, ...)");
1540 /* I died trying. */
1541 }
1542 break;
1543 }
1544 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001545 WSTOPSIG(status) == SIGTRAP ?
1546 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 if (errno != ESRCH)
1548 perror("detach: ptrace(PTRACE_CONT, ...)");
1549 break;
1550 }
1551 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001552#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553
1554#if defined(SUNOS4)
1555 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1556 if (sig && kill(tcp->pid, sig) < 0)
1557 perror("detach: kill");
1558 sig = 0;
1559 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1560 perror("detach: ptrace(PTRACE_DETACH, ...)");
1561#endif /* SUNOS4 */
1562
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001563#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001564 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001565#endif
1566
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 if (!qflag)
1568 fprintf(stderr, "Process %u detached\n", tcp->pid);
1569
1570 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001571
1572#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001573 if (zombie != NULL) {
1574 /* TCP no longer exists therefore you must not detach () it. */
1575 droptcb(zombie);
1576 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001577#endif
1578
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579 return error;
1580}
1581
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001582#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583
1584static void
1585reaper(sig)
1586int sig;
1587{
1588 int pid;
1589 int status;
1590
1591 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1592#if 0
1593 struct tcb *tcp;
1594
1595 tcp = pid2tcb(pid);
1596 if (tcp)
1597 droptcb(tcp);
1598#endif
1599 }
1600}
1601
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001602#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603
1604static void
1605cleanup()
1606{
1607 int i;
1608 struct tcb *tcp;
1609
Roland McGrathee9d4352002-12-18 04:16:10 +00001610 for (i = 0; i < tcbtabsize; i++) {
1611 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612 if (!(tcp->flags & TCB_INUSE))
1613 continue;
1614 if (debug)
1615 fprintf(stderr,
1616 "cleanup: looking at pid %u\n", tcp->pid);
1617 if (tcp_last &&
1618 (!outfname || followfork < 2 || tcp_last == tcp)) {
1619 tprintf(" <unfinished ...>\n");
1620 tcp_last = NULL;
1621 }
1622 if (tcp->flags & TCB_ATTACHED)
1623 detach(tcp, 0);
1624 else {
1625 kill(tcp->pid, SIGCONT);
1626 kill(tcp->pid, SIGTERM);
1627 }
1628 }
1629 if (cflag)
1630 call_summary(outf);
1631}
1632
1633static void
1634interrupt(sig)
1635int sig;
1636{
1637 interrupted = 1;
1638}
1639
1640#ifndef HAVE_STRERROR
1641
Roland McGrath6d2b3492002-12-30 00:51:30 +00001642#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643extern int sys_nerr;
1644extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001645#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646
1647const char *
1648strerror(errno)
1649int errno;
1650{
1651 static char buf[64];
1652
1653 if (errno < 1 || errno >= sys_nerr) {
1654 sprintf(buf, "Unknown error %d", errno);
1655 return buf;
1656 }
1657 return sys_errlist[errno];
1658}
1659
1660#endif /* HAVE_STERRROR */
1661
1662#ifndef HAVE_STRSIGNAL
1663
Roland McGrath8f474e02003-01-14 07:53:33 +00001664#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001665extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001667#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1668extern char *_sys_siglist[];
1669#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670
1671const char *
1672strsignal(sig)
1673int sig;
1674{
1675 static char buf[64];
1676
1677 if (sig < 1 || sig >= NSIG) {
1678 sprintf(buf, "Unknown signal %d", sig);
1679 return buf;
1680 }
1681#ifdef HAVE__SYS_SIGLIST
1682 return _sys_siglist[sig];
1683#else
1684 return sys_siglist[sig];
1685#endif
1686}
1687
1688#endif /* HAVE_STRSIGNAL */
1689
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001690#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691
1692static void
1693rebuild_pollv()
1694{
1695 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696
Roland McGrathee9d4352002-12-18 04:16:10 +00001697 if (pollv != NULL)
1698 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001699 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001700 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001701 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001702 exit(1);
1703 }
1704
Roland McGrathca16be82003-01-10 19:55:28 +00001705 for (i = j = 0; i < tcbtabsize; i++) {
1706 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707 if (!(tcp->flags & TCB_INUSE))
1708 continue;
1709 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001710 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 j++;
1712 }
1713 if (j != nprocs) {
1714 fprintf(stderr, "strace: proc miscount\n");
1715 exit(1);
1716 }
1717}
1718
1719#ifndef HAVE_POLLABLE_PROCFS
1720
1721static void
1722proc_poll_open()
1723{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724 int i;
1725
1726 if (pipe(proc_poll_pipe) < 0) {
1727 perror("pipe");
1728 exit(1);
1729 }
1730 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001731 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 exit(1);
1733 }
1734 }
1735}
1736
1737static int
1738proc_poll(pollv, nfds, timeout)
1739struct pollfd *pollv;
1740int nfds;
1741int timeout;
1742{
1743 int i;
1744 int n;
1745 struct proc_pollfd pollinfo;
1746
1747 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1748 return n;
1749 if (n != sizeof(struct proc_pollfd)) {
1750 fprintf(stderr, "panic: short read: %d\n", n);
1751 exit(1);
1752 }
1753 for (i = 0; i < nprocs; i++) {
1754 if (pollv[i].fd == pollinfo.fd)
1755 pollv[i].revents = pollinfo.revents;
1756 else
1757 pollv[i].revents = 0;
1758 }
1759 poller_pid = pollinfo.pid;
1760 return 1;
1761}
1762
1763static void
1764wakeup_handler(sig)
1765int sig;
1766{
1767}
1768
1769static void
1770proc_poller(pfd)
1771int pfd;
1772{
1773 struct proc_pollfd pollinfo;
1774 struct sigaction sa;
1775 sigset_t blocked_set, empty_set;
1776 int i;
1777 int n;
1778 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001779#ifdef FREEBSD
1780 struct procfs_status pfs;
1781#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782
1783 switch (fork()) {
1784 case -1:
1785 perror("fork");
1786 _exit(0);
1787 case 0:
1788 break;
1789 default:
1790 return;
1791 }
1792
1793 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1794 sa.sa_flags = 0;
1795 sigemptyset(&sa.sa_mask);
1796 sigaction(SIGHUP, &sa, NULL);
1797 sigaction(SIGINT, &sa, NULL);
1798 sigaction(SIGQUIT, &sa, NULL);
1799 sigaction(SIGPIPE, &sa, NULL);
1800 sigaction(SIGTERM, &sa, NULL);
1801 sa.sa_handler = wakeup_handler;
1802 sigaction(SIGUSR1, &sa, NULL);
1803 sigemptyset(&blocked_set);
1804 sigaddset(&blocked_set, SIGUSR1);
1805 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1806 sigemptyset(&empty_set);
1807
1808 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1809 perror("getrlimit(RLIMIT_NOFILE, ...)");
1810 _exit(0);
1811 }
1812 n = rl.rlim_cur;
1813 for (i = 0; i < n; i++) {
1814 if (i != pfd && i != proc_poll_pipe[1])
1815 close(i);
1816 }
1817
1818 pollinfo.fd = pfd;
1819 pollinfo.pid = getpid();
1820 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001821#ifndef FREEBSD
1822 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1823#else /* FREEBSD */
1824 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1825#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001826 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001827 switch (errno) {
1828 case EINTR:
1829 continue;
1830 case EBADF:
1831 pollinfo.revents = POLLERR;
1832 break;
1833 case ENOENT:
1834 pollinfo.revents = POLLHUP;
1835 break;
1836 default:
1837 perror("proc_poller: PIOCWSTOP");
1838 }
1839 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1840 _exit(0);
1841 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001842 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1844 sigsuspend(&empty_set);
1845 }
1846}
1847
1848#endif /* !HAVE_POLLABLE_PROCFS */
1849
1850static int
1851choose_pfd()
1852{
1853 int i, j;
1854 struct tcb *tcp;
1855
1856 static int last;
1857
1858 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001859 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860 /*
1861 * The previous process is ready to run again. We'll
1862 * let it do so if it is currently in a syscall. This
1863 * heuristic improves the readability of the trace.
1864 */
1865 tcp = pfd2tcb(pollv[last].fd);
1866 if (tcp && (tcp->flags & TCB_INSYSCALL))
1867 return pollv[last].fd;
1868 }
1869
1870 for (i = 0; i < nprocs; i++) {
1871 /* Let competing children run round robin. */
1872 j = (i + last + 1) % nprocs;
1873 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1874 tcp = pfd2tcb(pollv[j].fd);
1875 if (!tcp) {
1876 fprintf(stderr, "strace: lost proc\n");
1877 exit(1);
1878 }
1879 droptcb(tcp);
1880 return -1;
1881 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001882 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 last = j;
1884 return pollv[j].fd;
1885 }
1886 }
1887 fprintf(stderr, "strace: nothing ready\n");
1888 exit(1);
1889}
1890
1891static int
1892trace()
1893{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001894#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001895 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001896#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897 struct tcb *tcp;
1898 int pfd;
1899 int what;
1900 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001901 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902
1903 for (;;) {
1904 if (interactive)
1905 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1906
1907 if (nprocs == 0)
1908 break;
1909
1910 switch (nprocs) {
1911 case 1:
1912#ifndef HAVE_POLLABLE_PROCFS
1913 if (proc_poll_pipe[0] == -1) {
1914#endif
1915 tcp = pid2tcb(0);
1916 if (!tcp)
1917 continue;
1918 pfd = tcp->pfd;
1919 if (pfd == -1)
1920 continue;
1921 break;
1922#ifndef HAVE_POLLABLE_PROCFS
1923 }
1924 /* fall through ... */
1925#endif /* !HAVE_POLLABLE_PROCFS */
1926 default:
1927#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001928#ifdef POLL_HACK
1929 /* On some systems (e.g. UnixWare) we get too much ugly
1930 "unfinished..." stuff when multiple proceses are in
1931 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001932
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001933 if (in_syscall) {
1934 struct pollfd pv;
1935 tcp = in_syscall;
1936 in_syscall = NULL;
1937 pv.fd = tcp->pfd;
1938 pv.events = POLLWANT;
1939 if ((what = poll (&pv, 1, 1)) < 0) {
1940 if (interrupted)
1941 return 0;
1942 continue;
1943 }
1944 else if (what == 1 && pv.revents & POLLWANT) {
1945 goto FOUND;
1946 }
1947 }
1948#endif
1949
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 if (poll(pollv, nprocs, INFTIM) < 0) {
1951 if (interrupted)
1952 return 0;
1953 continue;
1954 }
1955#else /* !HAVE_POLLABLE_PROCFS */
1956 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1957 if (interrupted)
1958 return 0;
1959 continue;
1960 }
1961#endif /* !HAVE_POLLABLE_PROCFS */
1962 pfd = choose_pfd();
1963 if (pfd == -1)
1964 continue;
1965 break;
1966 }
1967
1968 /* Look up `pfd' in our table. */
1969 if ((tcp = pfd2tcb(pfd)) == NULL) {
1970 fprintf(stderr, "unknown pfd: %u\n", pfd);
1971 exit(1);
1972 }
John Hughesb6643082002-05-23 11:02:22 +00001973#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001974 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001975#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976 /* Get the status of the process. */
1977 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001978#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001979 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001980#else /* FREEBSD */
1981 /* Thanks to some scheduling mystery, the first poller
1982 sometimes waits for the already processed end of fork
1983 event. Doing a non blocking poll here solves the problem. */
1984 if (proc_poll_pipe[0] != -1)
1985 ioctl_result = IOCTL_STATUS (tcp);
1986 else
1987 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001988#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989 ioctl_errno = errno;
1990#ifndef HAVE_POLLABLE_PROCFS
1991 if (proc_poll_pipe[0] != -1) {
1992 if (ioctl_result < 0)
1993 kill(poller_pid, SIGKILL);
1994 else
1995 kill(poller_pid, SIGUSR1);
1996 }
1997#endif /* !HAVE_POLLABLE_PROCFS */
1998 }
1999 if (interrupted)
2000 return 0;
2001
2002 if (interactive)
2003 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2004
2005 if (ioctl_result < 0) {
2006 /* Find out what happened if it failed. */
2007 switch (ioctl_errno) {
2008 case EINTR:
2009 case EBADF:
2010 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002011#ifdef FREEBSD
2012 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002013#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002014 case ENOENT:
2015 droptcb(tcp);
2016 continue;
2017 default:
2018 perror("PIOCWSTOP");
2019 exit(1);
2020 }
2021 }
2022
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002023#ifdef FREEBSD
2024 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2025 /* discard first event for a syscall we never entered */
2026 IOCTL (tcp->pfd, PIOCRUN, 0);
2027 continue;
2028 }
Roland McGrath553a6092002-12-16 20:40:39 +00002029#endif
2030
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 /* clear the just started flag */
2032 tcp->flags &= ~TCB_STARTUP;
2033
2034 /* set current output file */
2035 outf = tcp->outf;
2036
2037 if (cflag) {
2038 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002039#ifdef FREEBSD
2040 char buf[1024];
2041 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002043 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2044 buf[len] = '\0';
2045 sscanf(buf,
2046 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2047 &stime.tv_sec, &stime.tv_usec);
2048 } else
2049 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002050#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002051 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2052 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002053#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2055 tcp->stime = stime;
2056 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 what = tcp->status.PR_WHAT;
2058 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002059#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002060 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002061 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2062 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063 if (trace_syscall(tcp) < 0) {
2064 fprintf(stderr, "syscall trouble\n");
2065 exit(1);
2066 }
2067 }
2068 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002069#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002071#ifdef POLL_HACK
2072 in_syscall = tcp;
2073#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002074 case PR_SYSEXIT:
2075 if (trace_syscall(tcp) < 0) {
2076 fprintf(stderr, "syscall trouble\n");
2077 exit(1);
2078 }
2079 break;
2080 case PR_SIGNALLED:
2081 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2082 printleader(tcp);
2083 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002084 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002085 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002086#ifdef PR_INFO
2087 if (tcp->status.PR_INFO.si_signo == what) {
2088 printleader(tcp);
2089 tprintf(" siginfo=");
2090 printsiginfo(&tcp->status.PR_INFO, 1);
2091 printtrailer(tcp);
2092 }
2093#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002094 }
2095 break;
2096 case PR_FAULTED:
2097 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2098 printleader(tcp);
2099 tprintf("=== FAULT %d ===", what);
2100 printtrailer(tcp);
2101 }
2102 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002103#ifdef FREEBSD
2104 case 0: /* handle case we polled for nothing */
2105 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002108 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109 exit(1);
2110 break;
2111 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002112 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002113#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002114 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002115#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002116 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002117#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002118 perror("PIOCRUN");
2119 exit(1);
2120 }
2121 }
2122 return 0;
2123}
2124
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002125#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002126
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002127#ifdef TCB_GROUP_EXITING
2128/* Handle an exit detach or death signal that is taking all the
2129 related clone threads with it. This is called in three circumstances:
2130 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2131 SIG == 0 Continuing TCP will perform an exit_group syscall.
2132 SIG == other Continuing TCP with SIG will kill the process.
2133*/
2134static int
2135handle_group_exit(struct tcb *tcp, int sig)
2136{
2137 /* We need to locate our records of all the clone threads
2138 related to TCP, either its children or siblings. */
2139 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2140 ? tcp->parent
2141 : tcp->nclone_detached > 0
2142 ? tcp : NULL);
2143
2144 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002145 if (leader != NULL && leader != tcp &&
2146 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002147 fprintf(stderr,
2148 "PANIC: handle_group_exit: %d leader %d\n",
2149 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002150 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002151#ifndef USE_PROCFS
2152 resume_from_tcp (tcp);
2153#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002154 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002155 }
2156 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002157 /* Mark that we are taking the process down. */
2158 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002159 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002160 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002161 if (leader != NULL && leader != tcp)
2162 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002163 }
2164 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2165 perror("strace: ptrace(PTRACE_CONT, ...)");
2166 cleanup();
2167 return -1;
2168 }
2169 else {
Roland McGrath05690952004-10-20 01:00:27 +00002170 if (leader != NULL)
2171 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002172 if (leader != NULL && leader != tcp)
2173 droptcb(tcp);
2174 /* The leader will report to us as parent now,
2175 and then we'll get to the SIG==-1 case. */
2176 return 0;
2177 }
2178 }
2179
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002180 return 0;
2181}
2182#endif
2183
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184static int
2185trace()
2186{
2187 int pid;
2188 int wait_errno;
2189 int status;
2190 struct tcb *tcp;
2191#ifdef LINUX
2192 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002193#ifdef __WALL
2194 static int wait4_options = __WALL;
2195#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196#endif /* LINUX */
2197
2198 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002199 if (interrupted)
2200 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 if (interactive)
2202 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2203#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002204#ifdef __WALL
2205 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002206 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002207 /* this kernel does not support __WALL */
2208 wait4_options &= ~__WALL;
2209 errno = 0;
2210 pid = wait4(-1, &status, wait4_options,
2211 cflag ? &ru : NULL);
2212 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002213 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002214 /* most likely a "cloned" process */
2215 pid = wait4(-1, &status, __WCLONE,
2216 cflag ? &ru : NULL);
2217 if (pid == -1) {
2218 fprintf(stderr, "strace: clone wait4 "
2219 "failed: %s\n", strerror(errno));
2220 }
2221 }
2222#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002223 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002224#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225#endif /* LINUX */
2226#ifdef SUNOS4
2227 pid = wait(&status);
2228#endif /* SUNOS4 */
2229 wait_errno = errno;
2230 if (interactive)
2231 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2232
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 if (pid == -1) {
2234 switch (wait_errno) {
2235 case EINTR:
2236 continue;
2237 case ECHILD:
2238 /*
2239 * We would like to verify this case
2240 * but sometimes a race in Solbourne's
2241 * version of SunOS sometimes reports
2242 * ECHILD before sending us SIGCHILD.
2243 */
2244#if 0
2245 if (nprocs == 0)
2246 return 0;
2247 fprintf(stderr, "strace: proc miscount\n");
2248 exit(1);
2249#endif
2250 return 0;
2251 default:
2252 errno = wait_errno;
2253 perror("strace: wait");
2254 return -1;
2255 }
2256 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002257 if (pid == popen_pid) {
2258 if (WIFEXITED(status) || WIFSIGNALED(status))
2259 popen_pid = -1;
2260 continue;
2261 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002262 if (debug)
2263 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2264
2265 /* Look up `pid' in our table. */
2266 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002267#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002268 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002269 /* This is needed to go with the CLONE_PTRACE
2270 changes in process.c/util.c: we might see
2271 the child's initial trap before we see the
2272 parent return from the clone syscall.
2273 Leave the child suspended until the parent
2274 returns from its system call. Only then
2275 will we have the association of parent and
2276 child so that we know how to do clearbpt
2277 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002278 if (nprocs == tcbtabsize &&
2279 expand_tcbtab())
2280 tcp = NULL;
2281 else
2282 tcp = alloctcb(pid);
2283 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002284 kill(pid, SIGKILL); /* XXX */
2285 return 0;
2286 }
2287 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002288 if (!qflag)
2289 fprintf(stderr, "\
2290Process %d attached (waiting for parent)\n",
2291 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002292 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002293 else
2294 /* This can happen if a clone call used
2295 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002296#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002297 {
2298 fprintf(stderr, "unknown pid: %u\n", pid);
2299 if (WIFSTOPPED(status))
2300 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2301 exit(1);
2302 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002303 }
2304 /* set current output file */
2305 outf = tcp->outf;
2306 if (cflag) {
2307#ifdef LINUX
2308 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2309 tcp->stime = ru.ru_stime;
2310#endif /* !LINUX */
2311 }
2312
2313 if (tcp->flags & TCB_SUSPENDED) {
2314 /*
2315 * Apparently, doing any ptrace() call on a stopped
2316 * process, provokes the kernel to report the process
2317 * status again on a subsequent wait(), even if the
2318 * process has not been actually restarted.
2319 * Since we have inspected the arguments of suspended
2320 * processes we end up here testing for this case.
2321 */
2322 continue;
2323 }
2324 if (WIFSIGNALED(status)) {
2325 if (!cflag
2326 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2327 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002328 tprintf("+++ killed by %s %s+++",
2329 signame(WTERMSIG(status)),
2330#ifdef WCOREDUMP
2331 WCOREDUMP(status) ? "(core dumped) " :
2332#endif
2333 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 printtrailer(tcp);
2335 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002336#ifdef TCB_GROUP_EXITING
2337 handle_group_exit(tcp, -1);
2338#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002339 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002340#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341 continue;
2342 }
2343 if (WIFEXITED(status)) {
2344 if (debug)
2345 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002346 if ((tcp->flags & TCB_ATTACHED)
2347#ifdef TCB_GROUP_EXITING
2348 && !(tcp->parent && (tcp->parent->flags &
2349 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002350 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002351#endif
2352 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002353 fprintf(stderr,
2354 "PANIC: attached pid %u exited\n",
2355 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002356 if (tcp == tcp_last) {
2357 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2358 == TCB_INSYSCALL)
2359 tprintf(" <unfinished ... exit status %d>\n",
2360 WEXITSTATUS(status));
2361 tcp_last = NULL;
2362 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002363#ifdef TCB_GROUP_EXITING
2364 handle_group_exit(tcp, -1);
2365#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002366 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002367#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002368 continue;
2369 }
2370 if (!WIFSTOPPED(status)) {
2371 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2372 droptcb(tcp);
2373 continue;
2374 }
2375 if (debug)
2376 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002377 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378
Roland McGrath02203312007-06-11 22:06:31 +00002379 /*
2380 * Interestingly, the process may stop
2381 * with STOPSIG equal to some other signal
2382 * than SIGSTOP if we happend to attach
2383 * just before the process takes a signal.
2384 */
2385 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 /*
2387 * This flag is there to keep us in sync.
2388 * Next time this process stops it should
2389 * really be entering a system call.
2390 */
2391 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002392 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002393 /*
2394 * One example is a breakpoint inherited from
2395 * parent through fork ().
2396 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002397 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2398 droptcb(tcp);
2399 cleanup();
2400 return -1;
2401 }
2402 }
2403 goto tracing;
2404 }
2405
2406 if (WSTOPSIG(status) != SIGTRAP) {
2407 if (WSTOPSIG(status) == SIGSTOP &&
2408 (tcp->flags & TCB_SIGTRAPPED)) {
2409 /*
2410 * Trapped attempt to block SIGTRAP
2411 * Hope we are back in control now.
2412 */
2413 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2414 if (ptrace(PTRACE_SYSCALL,
2415 pid, (char *) 1, 0) < 0) {
2416 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2417 cleanup();
2418 return -1;
2419 }
2420 continue;
2421 }
2422 if (!cflag
2423 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002424 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002425#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002426# define PSR_RI 41
2427 struct siginfo si;
2428 unsigned long psr;
2429
2430 upeek(pid, PT_CR_IPSR, &psr);
2431 upeek(pid, PT_CR_IIP, &pc);
2432
2433 pc += (psr >> PSR_RI) & 0x3;
2434 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2435 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002436#elif defined PTRACE_GETSIGINFO
2437 if (WSTOPSIG(status) == SIGSEGV ||
2438 WSTOPSIG(status) == SIGBUS) {
2439 siginfo_t si;
2440 if (ptrace(PTRACE_GETSIGINFO, pid,
2441 0, &si) == 0)
2442 addr = (unsigned long)
2443 si.si_addr;
2444 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002445#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002446 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002447 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002448 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002449 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002450 printtrailer(tcp);
2451 }
Roland McGrath05690952004-10-20 01:00:27 +00002452 if (((tcp->flags & TCB_ATTACHED) ||
2453 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002455#ifdef TCB_GROUP_EXITING
2456 handle_group_exit(tcp, WSTOPSIG(status));
2457#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002458 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002459#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002460 continue;
2461 }
2462 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2463 WSTOPSIG(status)) < 0) {
2464 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2465 cleanup();
2466 return -1;
2467 }
2468 tcp->flags &= ~TCB_SUSPENDED;
2469 continue;
2470 }
Roland McGrath02203312007-06-11 22:06:31 +00002471 /* we handled the STATUS, we are permitted to interrupt now. */
2472 if (interrupted)
2473 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002474 if (trace_syscall(tcp) < 0) {
2475 if (tcp->flags & TCB_ATTACHED)
2476 detach(tcp, 0);
2477 else {
2478 ptrace(PTRACE_KILL,
2479 tcp->pid, (char *) 1, SIGTERM);
2480 droptcb(tcp);
2481 }
2482 continue;
2483 }
2484 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002485#ifdef TCB_GROUP_EXITING
2486 if (tcp->flags & TCB_GROUP_EXITING) {
2487 if (handle_group_exit(tcp, 0) < 0)
2488 return -1;
2489 continue;
2490 }
2491#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002492 if (tcp->flags & TCB_ATTACHED)
2493 detach(tcp, 0);
2494 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2495 perror("strace: ptrace(PTRACE_CONT, ...)");
2496 cleanup();
2497 return -1;
2498 }
2499 continue;
2500 }
2501 if (tcp->flags & TCB_SUSPENDED) {
2502 if (!qflag)
2503 fprintf(stderr, "Process %u suspended\n", pid);
2504 continue;
2505 }
2506 tracing:
2507 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2508 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2509 cleanup();
2510 return -1;
2511 }
2512 }
2513 return 0;
2514}
2515
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002516#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002517
2518static int curcol;
2519
2520#ifdef __STDC__
2521#include <stdarg.h>
2522#define VA_START(a, b) va_start(a, b)
2523#else
2524#include <varargs.h>
2525#define VA_START(a, b) va_start(a)
2526#endif
2527
2528void
2529#ifdef __STDC__
2530tprintf(const char *fmt, ...)
2531#else
2532tprintf(fmt, va_alist)
2533char *fmt;
2534va_dcl
2535#endif
2536{
2537 va_list args;
2538
2539 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002540 if (outf) {
2541 int n = vfprintf(outf, fmt, args);
2542 if (n < 0 && outf != stderr)
2543 perror(outfname == NULL
2544 ? "<writing to pipe>" : outfname);
2545 else
2546 curcol += n;
2547 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002548 va_end(args);
2549 return;
2550}
2551
2552void
2553printleader(tcp)
2554struct tcb *tcp;
2555{
2556 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2557 tcp_last->flags |= TCB_REPRINT;
2558 tprintf(" <unfinished ...>\n");
2559 }
2560 curcol = 0;
2561 if ((followfork == 1 || pflag_seen > 1) && outfname)
2562 tprintf("%-5d ", tcp->pid);
2563 else if (nprocs > 1 && !outfname)
2564 tprintf("[pid %5u] ", tcp->pid);
2565 if (tflag) {
2566 char str[sizeof("HH:MM:SS")];
2567 struct timeval tv, dtv;
2568 static struct timeval otv;
2569
2570 gettimeofday(&tv, NULL);
2571 if (rflag) {
2572 if (otv.tv_sec == 0)
2573 otv = tv;
2574 tv_sub(&dtv, &tv, &otv);
2575 tprintf("%6ld.%06ld ",
2576 (long) dtv.tv_sec, (long) dtv.tv_usec);
2577 otv = tv;
2578 }
2579 else if (tflag > 2) {
2580 tprintf("%ld.%06ld ",
2581 (long) tv.tv_sec, (long) tv.tv_usec);
2582 }
2583 else {
2584 time_t local = tv.tv_sec;
2585 strftime(str, sizeof(str), "%T", localtime(&local));
2586 if (tflag > 1)
2587 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2588 else
2589 tprintf("%s ", str);
2590 }
2591 }
2592 if (iflag)
2593 printcall(tcp);
2594}
2595
2596void
2597tabto(col)
2598int col;
2599{
2600 if (curcol < col)
2601 tprintf("%*s", col - curcol, "");
2602}
2603
2604void
2605printtrailer(tcp)
2606struct tcb *tcp;
2607{
2608 tprintf("\n");
2609 tcp_last = NULL;
2610}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002611
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002612#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002613
2614int mp_ioctl (int fd, int cmd, void *arg, int size) {
2615
2616 struct iovec iov[2];
2617 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002618
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002619 iov[0].iov_base = &cmd;
2620 iov[0].iov_len = sizeof cmd;
2621 if (arg) {
2622 ++n;
2623 iov[1].iov_base = arg;
2624 iov[1].iov_len = size;
2625 }
Roland McGrath553a6092002-12-16 20:40:39 +00002626
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002627 return writev (fd, iov, n);
2628}
2629
2630#endif