blob: 4e8604038dc8b00dd010898778f560d29df513cf [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
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101static int trace P((void));
102static void cleanup P((void));
103static void interrupt P((int sig));
104static sigset_t empty_set, blocked_set;
105
106#ifdef HAVE_SIG_ATOMIC_T
107static volatile sig_atomic_t interrupted;
108#else /* !HAVE_SIG_ATOMIC_T */
109#ifdef __STDC__
110static volatile int interrupted;
111#else /* !__STDC__ */
112static int interrupted;
113#endif /* !__STDC__ */
114#endif /* !HAVE_SIG_ATOMIC_T */
115
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000116#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117
118static struct tcb *pfd2tcb P((int pfd));
119static void reaper P((int sig));
120static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000121static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122
123#ifndef HAVE_POLLABLE_PROCFS
124
125static void proc_poll_open P((void));
126static void proc_poller P((int pfd));
127
128struct proc_pollfd {
129 int fd;
130 int revents;
131 int pid;
132};
133
134static int poller_pid;
135static int proc_poll_pipe[2] = { -1, -1 };
136
137#endif /* !HAVE_POLLABLE_PROCFS */
138
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000139#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000140#define POLLWANT POLLWRNORM
141#else
142#define POLLWANT POLLPRI
143#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000144#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145
146static void
147usage(ofp, exitval)
148FILE *ofp;
149int exitval;
150{
151 fprintf(ofp, "\
152usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000153 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
154 [command [arg ...]]\n\
155 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
156 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157-c -- count time, calls, and errors for each syscall and report summary\n\
158-f -- follow forks, -ff -- with output into separate files\n\
159-F -- attempt to follow vforks, -h -- print help message\n\
160-i -- print instruction pointer at time of syscall\n\
161-q -- suppress messages about attaching, detaching, etc.\n\
162-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
163-T -- print time spent in each syscall, -V -- print version\n\
164-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
165-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
166-a column -- alignment COLUMN for printing syscall results (default %d)\n\
167-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
168 options: trace, abbrev, verbose, raw, signal, read, or write\n\
169-o file -- send trace output to FILE instead of stderr\n\
170-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
171-p pid -- trace process with process id PID, may be repeated\n\
172-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
173-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
174-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000175-E var=val -- put var=val in the environment for command\n\
176-E var -- remove var from the environment for command\n\
177" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000178-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000179 */
180, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181 exit(exitval);
182}
183
184#ifdef SVR4
185#ifdef MIPS
186void
187foobar()
188{
189}
190#endif /* MIPS */
191#endif /* SVR4 */
192
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000193static int
194set_cloexec_flag(int fd)
195{
196 int flags, newflags;
197
198 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
199 {
200 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
201 progname, strerror(errno));
202 return -1;
203 }
204
205 newflags = flags | FD_CLOEXEC;
206 if (flags == newflags)
207 return 0;
208
209 if (fcntl(fd, F_SETFD, newflags) < 0)
210 {
211 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
212 progname, strerror(errno));
213 return -1;
214 }
215
216 return 0;
217}
218
219/*
220 * When strace is setuid executable, we have to swap uids
221 * before and after filesystem and process management operations.
222 */
223static void
224swap_uid(void)
225{
226#ifndef SVR4
227 int euid = geteuid(), uid = getuid();
228
229 if (euid != uid && setreuid(euid, uid) < 0)
230 {
231 fprintf(stderr, "%s: setreuid: %s\n",
232 progname, strerror(errno));
233 exit(1);
234 }
235#endif
236}
237
238static FILE *
239strace_fopen(const char *path, const char *mode)
240{
241 FILE *fp;
242
243 swap_uid();
244 if ((fp = fopen(path, mode)) == NULL)
245 fprintf(stderr, "%s: can't fopen '%s': %s\n",
246 progname, path, strerror(errno));
247 swap_uid();
248 if (fp && set_cloexec_flag(fileno(fp)) < 0)
249 {
250 fclose(fp);
251 fp = NULL;
252 }
253 return fp;
254}
255
256static int popen_pid = -1;
257
258#ifndef _PATH_BSHELL
259# define _PATH_BSHELL "/bin/sh"
260#endif
261
262/*
263 * We cannot use standard popen(3) here because we have to distinguish
264 * popen child process from other processes we trace, and standard popen(3)
265 * does not export its child's pid.
266 */
267static FILE *
268strace_popen(const char *command)
269{
270 int fds[2];
271
272 swap_uid();
273 if (pipe(fds) < 0)
274 {
275 fprintf(stderr, "%s: pipe: %s\n",
276 progname, strerror(errno));
277 swap_uid();
278 return NULL;
279 }
280
281 if (set_cloexec_flag(fds[1]) < 0)
282 {
283 close(fds[0]);
284 close(fds[1]);
285 swap_uid();
286 return NULL;
287 }
288
289 if ((popen_pid = fork()) == -1)
290 {
291 fprintf(stderr, "%s: fork: %s\n",
292 progname, strerror(errno));
293 close(fds[0]);
294 close(fds[1]);
295 swap_uid();
296 return NULL;
297 }
298
299 if (popen_pid)
300 {
301 /* parent */
302 close(fds[0]);
303 swap_uid();
304 return fdopen(fds[1], "w");
305 } else
306 {
307 /* child */
308 close(fds[1]);
309 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
310 {
311 fprintf(stderr, "%s: dup2: %s\n",
312 progname, strerror(errno));
313 _exit(1);
314 }
315 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
316 fprintf(stderr, "%s: execl: %s: %s\n",
317 progname, _PATH_BSHELL, strerror(errno));
318 _exit(1);
319 }
320}
321
322static int
323newoutf(struct tcb *tcp)
324{
325 if (outfname && followfork > 1) {
326 char name[MAXPATHLEN];
327 FILE *fp;
328
329 sprintf(name, "%s.%u", outfname, tcp->pid);
330 if ((fp = strace_fopen(name, "w")) == NULL)
331 return -1;
332 tcp->outf = fp;
333 }
334 return 0;
335}
336
Roland McGrath02203312007-06-11 22:06:31 +0000337static void
338startup_attach(void)
339{
340 int tcbi;
341 struct tcb *tcp;
342
343 /*
344 * Block user interruptions as we would leave the traced
345 * process stopped (process state T) if we would terminate in
346 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
347 * We rely on cleanup () from this point on.
348 */
349 if (interactive)
350 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
351
352 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
353 tcp = tcbtab[tcbi];
354 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
355 continue;
356#ifdef LINUX
357 if (tcp->flags & TCB_CLONE_THREAD)
358 continue;
359#endif
360 /* Reinitialize the output since it may have changed. */
361 tcp->outf = outf;
362 if (newoutf(tcp) < 0)
363 exit(1);
364
365#ifdef USE_PROCFS
366 if (proc_open(tcp, 1) < 0) {
367 fprintf(stderr, "trouble opening proc file\n");
368 droptcb(tcp);
369 continue;
370 }
371#else /* !USE_PROCFS */
372# ifdef LINUX
373 if (followfork) {
374 char procdir[MAXPATHLEN];
375 DIR *dir;
376
377 sprintf(procdir, "/proc/%d/task", tcp->pid);
378 dir = opendir(procdir);
379 if (dir != NULL) {
380 unsigned int ntid = 0, nerr = 0;
381 struct dirent *de;
382 int tid;
383 while ((de = readdir(dir)) != NULL) {
384 if (de->d_fileno == 0 ||
385 de->d_name[0] == '.')
386 continue;
387 tid = atoi(de->d_name);
388 if (tid <= 0)
389 continue;
390 ++ntid;
391 if (ptrace(PTRACE_ATTACH, tid,
392 (char *) 1, 0) < 0)
393 ++nerr;
394 else if (tid != tcbtab[tcbi]->pid) {
395 if (nprocs == tcbtabsize &&
396 expand_tcbtab())
397 tcp = NULL;
398 else
399 tcp = alloctcb(tid);
400 if (tcp == NULL)
401 exit(1);
402 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
403 tcbtab[tcbi]->nchildren++;
404 tcbtab[tcbi]->nclone_threads++;
405 tcbtab[tcbi]->nclone_detached++;
406 tcp->parent = tcbtab[tcbi];
407 }
408 if (interactive) {
409 sigprocmask(SIG_SETMASK, &empty_set, NULL);
410 if (interrupted)
411 return;
412 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
413 }
414 }
415 closedir(dir);
416 if (nerr == ntid) {
417 perror("attach: ptrace(PTRACE_ATTACH, ...)");
418 droptcb(tcp);
419 continue;
420 }
421 if (!qflag) {
422 ntid -= nerr;
423 if (ntid > 1)
424 fprintf(stderr, "\
425Process %u attached with %u threads - interrupt to quit\n",
426 tcp->pid, ntid);
427 else
428 fprintf(stderr, "\
429Process %u attached - interrupt to quit\n",
430 tcp->pid);
431 }
432 continue;
433 }
434 }
435# endif
436 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
437 perror("attach: ptrace(PTRACE_ATTACH, ...)");
438 droptcb(tcp);
439 continue;
440 }
441 /* INTERRUPTED is going to be checked at the top of TRACE. */
442#endif /* !USE_PROCFS */
443 if (!qflag)
444 fprintf(stderr,
445 "Process %u attached - interrupt to quit\n",
446 tcp->pid);
447 }
448
449 if (interactive)
450 sigprocmask(SIG_SETMASK, &empty_set, NULL);
451}
452
453static void
454startup_child (char **argv)
455{
456 struct stat statbuf;
457 const char *filename;
458 char pathname[MAXPATHLEN];
459 int pid = 0;
460 struct tcb *tcp;
461
462 filename = argv[0];
463 if (strchr(filename, '/')) {
464 if (strlen(filename) > sizeof pathname - 1) {
465 errno = ENAMETOOLONG;
466 perror("strace: exec");
467 exit(1);
468 }
469 strcpy(pathname, filename);
470 }
471#ifdef USE_DEBUGGING_EXEC
472 /*
473 * Debuggers customarily check the current directory
474 * first regardless of the path but doing that gives
475 * security geeks a panic attack.
476 */
477 else if (stat(filename, &statbuf) == 0)
478 strcpy(pathname, filename);
479#endif /* USE_DEBUGGING_EXEC */
480 else {
481 char *path;
482 int m, n, len;
483
484 for (path = getenv("PATH"); path && *path; path += m) {
485 if (strchr(path, ':')) {
486 n = strchr(path, ':') - path;
487 m = n + 1;
488 }
489 else
490 m = n = strlen(path);
491 if (n == 0) {
492 if (!getcwd(pathname, MAXPATHLEN))
493 continue;
494 len = strlen(pathname);
495 }
496 else if (n > sizeof pathname - 1)
497 continue;
498 else {
499 strncpy(pathname, path, n);
500 len = n;
501 }
502 if (len && pathname[len - 1] != '/')
503 pathname[len++] = '/';
504 strcpy(pathname + len, filename);
505 if (stat(pathname, &statbuf) == 0 &&
506 /* Accept only regular files
507 with some execute bits set.
508 XXX not perfect, might still fail */
509 S_ISREG(statbuf.st_mode) &&
510 (statbuf.st_mode & 0111))
511 break;
512 }
513 }
514 if (stat(pathname, &statbuf) < 0) {
515 fprintf(stderr, "%s: %s: command not found\n",
516 progname, filename);
517 exit(1);
518 }
519 switch (pid = fork()) {
520 case -1:
521 perror("strace: fork");
522 cleanup();
523 exit(1);
524 break;
525 case 0: {
526#ifdef USE_PROCFS
527 if (outf != stderr) close (fileno (outf));
528#ifdef MIPS
529 /* Kludge for SGI, see proc_open for details. */
530 sa.sa_handler = foobar;
531 sa.sa_flags = 0;
532 sigemptyset(&sa.sa_mask);
533 sigaction(SIGINT, &sa, NULL);
534#endif /* MIPS */
535#ifndef FREEBSD
536 pause();
537#else /* FREEBSD */
538 kill(getpid(), SIGSTOP); /* stop HERE */
539#endif /* FREEBSD */
540#else /* !USE_PROCFS */
541 if (outf!=stderr)
542 close(fileno (outf));
543
544 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
545 perror("strace: ptrace(PTRACE_TRACEME, ...)");
546 exit(1);
547 }
548 if (debug)
549 kill(getpid(), SIGSTOP);
550
551 if (username != NULL || geteuid() == 0) {
552 uid_t run_euid = run_uid;
553 gid_t run_egid = run_gid;
554
555 if (statbuf.st_mode & S_ISUID)
556 run_euid = statbuf.st_uid;
557 if (statbuf.st_mode & S_ISGID)
558 run_egid = statbuf.st_gid;
559
560 /*
561 * It is important to set groups before we
562 * lose privileges on setuid.
563 */
564 if (username != NULL) {
565 if (initgroups(username, run_gid) < 0) {
566 perror("initgroups");
567 exit(1);
568 }
569 if (setregid(run_gid, run_egid) < 0) {
570 perror("setregid");
571 exit(1);
572 }
573 if (setreuid(run_uid, run_euid) < 0) {
574 perror("setreuid");
575 exit(1);
576 }
577 }
578 }
579 else
580 setreuid(run_uid, run_uid);
581
582 /*
583 * Induce an immediate stop so that the parent
584 * will resume us with PTRACE_SYSCALL and display
585 * this execve call normally.
586 */
587 kill(getpid(), SIGSTOP);
588#endif /* !USE_PROCFS */
589
590 execv(pathname, argv);
591 perror("strace: exec");
592 _exit(1);
593 break;
594 }
595 default:
596 if ((tcp = alloctcb(pid)) == NULL) {
597 cleanup();
598 exit(1);
599 }
600#ifdef USE_PROCFS
601 if (proc_open(tcp, 0) < 0) {
602 fprintf(stderr, "trouble opening proc file\n");
603 cleanup();
604 exit(1);
605 }
606#endif /* USE_PROCFS */
607 break;
608 }
609}
610
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000611int
612main(argc, argv)
613int argc;
614char *argv[];
615{
616 extern int optind;
617 extern char *optarg;
618 struct tcb *tcp;
619 int c, pid = 0;
620 struct sigaction sa;
621
622 static char buf[BUFSIZ];
623
Roland McGrathee9d4352002-12-18 04:16:10 +0000624 /* Allocate the initial tcbtab. */
625 tcbtabsize = argc; /* Surely enough for all -p args. */
626 tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
627 tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
628 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
629 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
630
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 progname = argv[0];
632 outf = stderr;
633 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000634 set_sortby(DEFAULT_SORTBY);
635 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000636 qualify("trace=all");
637 qualify("abbrev=all");
638 qualify("verbose=all");
639 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000640 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000641 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000642 switch (c) {
643 case 'c':
644 cflag++;
645 dtime++;
646 break;
647 case 'd':
648 debug++;
649 break;
650 case 'f':
651 followfork++;
652 break;
653 case 'F':
654 followvfork++;
655 break;
656 case 'h':
657 usage(stdout, 0);
658 break;
659 case 'i':
660 iflag++;
661 break;
662 case 'q':
663 qflag++;
664 break;
665 case 'r':
666 rflag++;
667 tflag++;
668 break;
669 case 't':
670 tflag++;
671 break;
672 case 'T':
673 dtime++;
674 break;
675 case 'x':
676 xflag++;
677 break;
678 case 'v':
679 qualify("abbrev=none");
680 break;
681 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000682 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683 exit(0);
684 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000685 case 'z':
686 not_failing_only = 1;
687 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688 case 'a':
689 acolumn = atoi(optarg);
690 break;
691 case 'e':
692 qualify(optarg);
693 break;
694 case 'o':
695 outfname = strdup(optarg);
696 break;
697 case 'O':
698 set_overhead(atoi(optarg));
699 break;
700 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000701 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000702 fprintf(stderr, "%s: Invalid process id: %s\n",
703 progname, optarg);
704 break;
705 }
706 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000707 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000708 break;
709 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000710 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000711 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712 progname);
713 exit(1);
714 }
715 tcp->flags |= TCB_ATTACHED;
716 pflag_seen++;
717 break;
718 case 's':
719 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000720 if (max_strlen < 0) {
721 fprintf(stderr,
722 "%s: invalid -s argument: %s\n",
723 progname, optarg);
724 exit(1);
725 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 break;
727 case 'S':
728 set_sortby(optarg);
729 break;
730 case 'u':
731 username = strdup(optarg);
732 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000733 case 'E':
734 if (putenv(optarg) < 0) {
735 fprintf(stderr, "%s: out of memory\n",
736 progname);
737 exit(1);
738 }
739 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000740 default:
741 usage(stderr, 1);
742 break;
743 }
744 }
745
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000746 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000747 usage(stderr, 1);
748
Roland McGrathcb9def62006-04-25 07:48:03 +0000749 if (followfork > 1 && cflag) {
750 fprintf(stderr,
751 "%s: -c and -ff are mutually exclusive options\n",
752 progname);
753 exit(1);
754 }
755
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 /* See if they want to run as another user. */
757 if (username != NULL) {
758 struct passwd *pent;
759
760 if (getuid() != 0 || geteuid() != 0) {
761 fprintf(stderr,
762 "%s: you must be root to use the -u option\n",
763 progname);
764 exit(1);
765 }
766 if ((pent = getpwnam(username)) == NULL) {
767 fprintf(stderr, "%s: cannot find user `%s'\n",
768 progname, optarg);
769 exit(1);
770 }
771 run_uid = pent->pw_uid;
772 run_gid = pent->pw_gid;
773 }
774 else {
775 run_uid = getuid();
776 run_gid = getgid();
777 }
778
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 /* Check if they want to redirect the output. */
780 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000781 /* See if they want to pipe the output. */
782 if (outfname[0] == '|' || outfname[0] == '!') {
783 /*
784 * We can't do the <outfname>.PID funny business
785 * when using popen, so prohibit it.
786 */
787 if (followfork > 1) {
788 fprintf(stderr, "\
789%s: piping the output and -ff are mutually exclusive options\n",
790 progname);
791 exit(1);
792 }
793
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000794 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000795 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000796 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000797 else if (followfork <= 1 &&
798 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000799 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800 }
801
Roland McGrath37b9a662003-11-07 02:26:54 +0000802 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000804 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000807 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000808
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000809 sigemptyset(&empty_set);
810 sigemptyset(&blocked_set);
811 sa.sa_handler = SIG_IGN;
812 sigemptyset(&sa.sa_mask);
813 sa.sa_flags = 0;
814 sigaction(SIGTTOU, &sa, NULL);
815 sigaction(SIGTTIN, &sa, NULL);
816 if (interactive) {
817 sigaddset(&blocked_set, SIGHUP);
818 sigaddset(&blocked_set, SIGINT);
819 sigaddset(&blocked_set, SIGQUIT);
820 sigaddset(&blocked_set, SIGPIPE);
821 sigaddset(&blocked_set, SIGTERM);
822 sa.sa_handler = interrupt;
823#ifdef SUNOS4
824 /* POSIX signals on sunos4.1 are a little broken. */
825 sa.sa_flags = SA_INTERRUPT;
826#endif /* SUNOS4 */
827 }
828 sigaction(SIGHUP, &sa, NULL);
829 sigaction(SIGINT, &sa, NULL);
830 sigaction(SIGQUIT, &sa, NULL);
831 sigaction(SIGPIPE, &sa, NULL);
832 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000833#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834 sa.sa_handler = reaper;
835 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000836#else
837 /* Make sure SIGCHLD has the default action so that waitpid
838 definitely works without losing track of children. The user
839 should not have given us a bogus state to inherit, but he might
840 have. Arguably we should detect SIG_IGN here and pass it on
841 to children, but probably noone really needs that. */
842 sa.sa_handler = SIG_DFL;
843 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000844#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845
Roland McGrath02203312007-06-11 22:06:31 +0000846 if (pflag_seen)
847 startup_attach();
848 else
849 startup_child(&argv[optind]);
850
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000851 if (trace() < 0)
852 exit(1);
853 cleanup();
854 exit(0);
855}
856
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000857int
858expand_tcbtab()
859{
860 /* Allocate some more TCBs and expand the table.
861 We don't want to relocate the TCBs because our
862 callers have pointers and it would be a pain.
863 So tcbtab is a table of pointers. Since we never
864 free the TCBs, we allocate a single chunk of many. */
865 struct tcb **newtab = (struct tcb **)
866 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
867 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
868 sizeof *newtcbs);
869 int i;
870 if (newtab == NULL || newtcbs == NULL) {
871 if (newtab != NULL)
872 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000873 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
874 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000875 return 1;
876 }
877 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
878 newtab[i] = &newtcbs[i - tcbtabsize];
879 tcbtabsize *= 2;
880 tcbtab = newtab;
881
882 return 0;
883}
884
885
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000887alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888{
889 int i;
890 struct tcb *tcp;
891
Roland McGrathee9d4352002-12-18 04:16:10 +0000892 for (i = 0; i < tcbtabsize; i++) {
893 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 if ((tcp->flags & TCB_INUSE) == 0) {
895 tcp->pid = pid;
896 tcp->parent = NULL;
897 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000898 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000899#ifdef TCB_CLONE_THREAD
900 tcp->nclone_threads = tcp->nclone_detached = 0;
901 tcp->nclone_waiting = 0;
902#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 tcp->flags = TCB_INUSE | TCB_STARTUP;
904 tcp->outf = outf; /* Initialise to current out file */
905 tcp->stime.tv_sec = 0;
906 tcp->stime.tv_usec = 0;
907 tcp->pfd = -1;
908 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000909 if (command_options_parsed)
910 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911 return tcp;
912 }
913 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000914 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915 return NULL;
916}
917
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000918#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919int
920proc_open(tcp, attaching)
921struct tcb *tcp;
922int attaching;
923{
924 char proc[32];
925 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000926#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000927 int i;
928 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000929 sigset_t signals;
930 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000931#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000932#ifndef HAVE_POLLABLE_PROCFS
933 static int last_pfd;
934#endif
935
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000936#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000937 /* Open the process pseudo-files in /proc. */
938 sprintf(proc, "/proc/%d/ctl", tcp->pid);
939 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 perror("strace: open(\"/proc/...\", ...)");
941 return -1;
942 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000943 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 return -1;
945 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000946 sprintf(proc, "/proc/%d/status", tcp->pid);
947 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
948 perror("strace: open(\"/proc/...\", ...)");
949 return -1;
950 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000951 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000952 return -1;
953 }
954 sprintf(proc, "/proc/%d/as", tcp->pid);
955 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
956 perror("strace: open(\"/proc/...\", ...)");
957 return -1;
958 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000959 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000960 return -1;
961 }
962#else
963 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000964#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000965 sprintf(proc, "/proc/%d", tcp->pid);
966 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000967#else /* FREEBSD */
968 sprintf(proc, "/proc/%d/mem", tcp->pid);
969 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
970#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000971 perror("strace: open(\"/proc/...\", ...)");
972 return -1;
973 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000974 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000975 return -1;
976 }
977#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000978#ifdef FREEBSD
979 sprintf(proc, "/proc/%d/regs", tcp->pid);
980 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
981 perror("strace: open(\"/proc/.../regs\", ...)");
982 return -1;
983 }
984 if (cflag) {
985 sprintf(proc, "/proc/%d/status", tcp->pid);
986 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
987 perror("strace: open(\"/proc/.../status\", ...)");
988 return -1;
989 }
990 } else
991 tcp->pfd_status = -1;
992#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000993 rebuild_pollv();
994 if (!attaching) {
995 /*
996 * Wait for the child to pause. Because of a race
997 * condition we have to poll for the event.
998 */
999 for (;;) {
1000 if (IOCTL_STATUS (tcp) < 0) {
1001 perror("strace: PIOCSTATUS");
1002 return -1;
1003 }
1004 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001005 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001006 }
1007 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001008#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001009 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001010 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001011 perror("strace: PIOCSTOP");
1012 return -1;
1013 }
Roland McGrath553a6092002-12-16 20:40:39 +00001014#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015#ifdef PIOCSET
1016 /* Set Run-on-Last-Close. */
1017 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001018 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 perror("PIOCSET PR_RLC");
1020 return -1;
1021 }
1022 /* Set or Reset Inherit-on-Fork. */
1023 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001024 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 perror("PIOC{SET,RESET} PR_FORK");
1026 return -1;
1027 }
1028#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001029#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1031 perror("PIOCSRLC");
1032 return -1;
1033 }
1034 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1035 perror("PIOC{S,R}FORK");
1036 return -1;
1037 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001038#else /* FREEBSD */
1039 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1040 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1041 perror("PIOCGFL");
1042 return -1;
1043 }
1044 arg &= ~PF_LINGER;
1045 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1046 perror("PIOCSFL");
1047 return -1;
1048 }
1049#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001051#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001052 /* Enable all syscall entries we care about. */
1053 premptyset(&syscalls);
1054 for (i = 1; i < MAX_QUALS; ++i) {
1055 if (i > (sizeof syscalls) * CHAR_BIT) break;
1056 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1057 }
1058 praddset (&syscalls, SYS_execve);
1059 if (followfork) {
1060 praddset (&syscalls, SYS_fork);
1061#ifdef SYS_forkall
1062 praddset (&syscalls, SYS_forkall);
1063#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001064#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001065 praddset (&syscalls, SYS_fork1);
1066#endif
1067#ifdef SYS_rfork1
1068 praddset (&syscalls, SYS_rfork1);
1069#endif
1070#ifdef SYS_rforkall
1071 praddset (&syscalls, SYS_rforkall);
1072#endif
1073 }
1074 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 perror("PIOCSENTRY");
1076 return -1;
1077 }
John Hughes19e49982001-10-19 08:59:12 +00001078 /* Enable the syscall exits. */
1079 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080 perror("PIOSEXIT");
1081 return -1;
1082 }
John Hughes19e49982001-10-19 08:59:12 +00001083 /* Enable signals we care about. */
1084 premptyset(&signals);
1085 for (i = 1; i < MAX_QUALS; ++i) {
1086 if (i > (sizeof signals) * CHAR_BIT) break;
1087 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1088 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001089 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001090 perror("PIOCSTRACE");
1091 return -1;
1092 }
John Hughes19e49982001-10-19 08:59:12 +00001093 /* Enable faults we care about */
1094 premptyset(&faults);
1095 for (i = 1; i < MAX_QUALS; ++i) {
1096 if (i > (sizeof faults) * CHAR_BIT) break;
1097 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1098 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001099 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 perror("PIOCSFAULT");
1101 return -1;
1102 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001103#else /* FREEBSD */
1104 /* set events flags. */
1105 arg = S_SIG | S_SCE | S_SCX ;
1106 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1107 perror("PIOCBIS");
1108 return -1;
1109 }
1110#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111 if (!attaching) {
1112#ifdef MIPS
1113 /*
1114 * The SGI PRSABORT doesn't work for pause() so
1115 * we send it a caught signal to wake it up.
1116 */
1117 kill(tcp->pid, SIGINT);
1118#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001119#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001121 arg = PRSABORT;
1122 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 perror("PIOCRUN");
1124 return -1;
1125 }
Roland McGrath553a6092002-12-16 20:40:39 +00001126#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001127#endif /* !MIPS*/
1128#ifdef FREEBSD
1129 /* wake up the child if it received the SIGSTOP */
1130 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001131#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 for (;;) {
1133 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001134 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 perror("PIOCWSTOP");
1136 return -1;
1137 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001138 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001139 tcp->flags &= ~TCB_INSYSCALL;
1140 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001141 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142 break;
1143 }
1144 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001145#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001146 arg = 0;
1147 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001148#else /* FREEBSD */
1149 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001150#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 perror("PIOCRUN");
1152 return -1;
1153 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001154#ifdef FREEBSD
1155 /* handle the case where we "opened" the child before
1156 it did the kill -STOP */
1157 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1158 tcp->status.PR_WHAT == SIGSTOP)
1159 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001160#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001162#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001164#else /* FREEBSD */
1165 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001166 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001167 /* We are attaching to an already running process.
1168 * Try to figure out the state of the process in syscalls,
1169 * to handle the first event well.
1170 * This is done by having a look at the "wchan" property of the
1171 * process, which tells where it is stopped (if it is). */
1172 FILE * status;
1173 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001174
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001175 sprintf(proc, "/proc/%d/status", tcp->pid);
1176 status = fopen(proc, "r");
1177 if (status &&
1178 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1179 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1180 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1181 strcmp(wchan, "stopevent")) {
1182 /* The process is asleep in the middle of a syscall.
1183 Fake the syscall entry event */
1184 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1185 tcp->status.PR_WHY = PR_SYSENTRY;
1186 trace_syscall(tcp);
1187 }
1188 if (status)
1189 fclose(status);
1190 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001191 }
1192#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193#ifndef HAVE_POLLABLE_PROCFS
1194 if (proc_poll_pipe[0] != -1)
1195 proc_poller(tcp->pfd);
1196 else if (nprocs > 1) {
1197 proc_poll_open();
1198 proc_poller(last_pfd);
1199 proc_poller(tcp->pfd);
1200 }
1201 last_pfd = tcp->pfd;
1202#endif /* !HAVE_POLLABLE_PROCFS */
1203 return 0;
1204}
1205
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001206#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001208struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209pid2tcb(pid)
1210int pid;
1211{
1212 int i;
1213 struct tcb *tcp;
1214
Roland McGrathee9d4352002-12-18 04:16:10 +00001215 for (i = 0; i < tcbtabsize; i++) {
1216 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 if (pid && tcp->pid != pid)
1218 continue;
1219 if (tcp->flags & TCB_INUSE)
1220 return tcp;
1221 }
1222 return NULL;
1223}
1224
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001225#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226
1227static struct tcb *
1228pfd2tcb(pfd)
1229int pfd;
1230{
1231 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232
Roland McGrathca16be82003-01-10 19:55:28 +00001233 for (i = 0; i < tcbtabsize; i++) {
1234 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235 if (tcp->pfd != pfd)
1236 continue;
1237 if (tcp->flags & TCB_INUSE)
1238 return tcp;
1239 }
1240 return NULL;
1241}
1242
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001243#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244
1245void
1246droptcb(tcp)
1247struct tcb *tcp;
1248{
1249 if (tcp->pid == 0)
1250 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001251#ifdef TCB_CLONE_THREAD
1252 if (tcp->nclone_threads > 0) {
1253 /* There are other threads left in this process, but this
1254 is the one whose PID represents the whole process.
1255 We need to keep this record around as a zombie until
1256 all the threads die. */
1257 tcp->flags |= TCB_EXITING;
1258 return;
1259 }
1260#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 nprocs--;
1262 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001263
Roland McGrathe29341c2003-01-10 20:14:20 +00001264 if (tcp->parent != NULL) {
1265 tcp->parent->nchildren--;
1266#ifdef TCB_CLONE_THREAD
1267 if (tcp->flags & TCB_CLONE_DETACHED)
1268 tcp->parent->nclone_detached--;
1269 if (tcp->flags & TCB_CLONE_THREAD)
1270 tcp->parent->nclone_threads--;
1271#endif
Roland McGrath09623452003-05-23 02:27:13 +00001272#ifdef TCB_CLONE_DETACHED
1273 if (!(tcp->flags & TCB_CLONE_DETACHED))
1274#endif
1275 tcp->parent->nzombies++;
Roland McGrathe29341c2003-01-10 20:14:20 +00001276 tcp->parent = NULL;
1277 }
1278
1279 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280 if (tcp->pfd != -1) {
1281 close(tcp->pfd);
1282 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001283#ifdef FREEBSD
1284 if (tcp->pfd_reg != -1) {
1285 close(tcp->pfd_reg);
1286 tcp->pfd_reg = -1;
1287 }
1288 if (tcp->pfd_status != -1) {
1289 close(tcp->pfd_status);
1290 tcp->pfd_status = -1;
1291 }
Roland McGrath553a6092002-12-16 20:40:39 +00001292#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001293#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001294 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295#endif
1296 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001297
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001298 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001300
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001301 tcp->outf = 0;
1302}
1303
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001304#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305
1306static int
1307resume(tcp)
1308struct tcb *tcp;
1309{
1310 if (tcp == NULL)
1311 return -1;
1312
1313 if (!(tcp->flags & TCB_SUSPENDED)) {
1314 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1315 return -1;
1316 }
1317 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001318#ifdef TCB_CLONE_THREAD
1319 if (tcp->flags & TCB_CLONE_THREAD)
1320 tcp->parent->nclone_waiting--;
1321#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322
1323 if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
1324 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
1325 return -1;
1326 }
1327
1328 if (!qflag)
1329 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1330 return 0;
1331}
1332
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001333#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334
1335/* detach traced process; continue with sig */
1336
1337static int
1338detach(tcp, sig)
1339struct tcb *tcp;
1340int sig;
1341{
1342 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001343#ifdef LINUX
Roland McGrath02203312007-06-11 22:06:31 +00001344 int status, resumed, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001345 struct tcb *zombie = NULL;
1346
1347 /* If the group leader is lingering only because of this other
1348 thread now dying, then detach the leader as well. */
1349 if ((tcp->flags & TCB_CLONE_THREAD) &&
1350 tcp->parent->nclone_threads == 1 &&
1351 (tcp->parent->flags & TCB_EXITING))
1352 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001353#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354
1355 if (tcp->flags & TCB_BPTSET)
1356 sig = SIGKILL;
1357
1358#ifdef LINUX
1359 /*
1360 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001361 * before detaching. Arghh. We go through hoops
1362 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001364#if defined(SPARC)
1365#undef PTRACE_DETACH
1366#define PTRACE_DETACH PTRACE_SUNDETACH
1367#endif
Roland McGrath02203312007-06-11 22:06:31 +00001368 /*
1369 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1370 * expected SIGSTOP. We must catch exactly one as otherwise the
1371 * detached process would be left stopped (process state T).
1372 */
1373 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1375 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001376 }
1377 else if (errno != ESRCH) {
1378 /* Shouldn't happen. */
1379 perror("detach: ptrace(PTRACE_DETACH, ...)");
1380 }
Roland McGrath134813a2007-06-02 00:07:33 +00001381 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1382 : tcp->pid),
1383 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001384 if (errno != ESRCH)
1385 perror("detach: checking sanity");
1386 }
Roland McGrath02203312007-06-11 22:06:31 +00001387 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1388 ? tcp->parent->pid : tcp->pid),
1389 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001390 if (errno != ESRCH)
1391 perror("detach: stopping child");
1392 }
Roland McGrath02203312007-06-11 22:06:31 +00001393 else
1394 catch_sigstop = 1;
1395 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001397#ifdef __WALL
1398 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1399 if (errno == ECHILD) /* Already gone. */
1400 break;
1401 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001402 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001403 break;
1404 }
1405#endif /* __WALL */
1406 /* No __WALL here. */
1407 if (waitpid(tcp->pid, &status, 0) < 0) {
1408 if (errno != ECHILD) {
1409 perror("detach: waiting");
1410 break;
1411 }
1412#ifdef __WCLONE
1413 /* If no processes, try clones. */
1414 if (wait4(tcp->pid, &status, __WCLONE,
1415 NULL) < 0) {
1416 if (errno != ECHILD)
1417 perror("detach: waiting");
1418 break;
1419 }
1420#endif /* __WCLONE */
1421 }
1422#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001423 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001424#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425 if (!WIFSTOPPED(status)) {
1426 /* Au revoir, mon ami. */
1427 break;
1428 }
1429 if (WSTOPSIG(status) == SIGSTOP) {
1430 if ((error = ptrace(PTRACE_DETACH,
Roland McGrath7bf10472002-12-16 20:42:50 +00001431 tcp->pid, (char *) 1, sig)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432 if (errno != ESRCH)
1433 perror("detach: ptrace(PTRACE_DETACH, ...)");
1434 /* I died trying. */
1435 }
1436 break;
1437 }
1438 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
Roland McGrath7bf10472002-12-16 20:42:50 +00001439 WSTOPSIG(status) == SIGTRAP ?
1440 0 : WSTOPSIG(status))) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441 if (errno != ESRCH)
1442 perror("detach: ptrace(PTRACE_CONT, ...)");
1443 break;
1444 }
1445 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001446#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447
1448#if defined(SUNOS4)
1449 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1450 if (sig && kill(tcp->pid, sig) < 0)
1451 perror("detach: kill");
1452 sig = 0;
1453 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1454 perror("detach: ptrace(PTRACE_DETACH, ...)");
1455#endif /* SUNOS4 */
1456
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001457#ifndef USE_PROCFS
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001458 resumed = 0;
1459
1460 /* XXX This won't always be quite right (but it never was).
1461 A waiter with argument 0 or < -1 is waiting for any pid in
1462 a particular pgrp, which this child might or might not be
1463 in. The waiter will only wake up if it's argument is -1
1464 or if it's waiting for tcp->pid's pgrp. It makes a
1465 difference to wake up a waiter when there might be more
1466 traced children, because it could get a false ECHILD
1467 error. OTOH, if this was the last child in the pgrp, then
1468 it ought to wake up and get ECHILD. We would have to
1469 search the system for all pid's in the pgrp to be sure.
1470
1471 && (t->waitpid == -1 ||
1472 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1473 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1474 */
1475
1476 if (tcp->parent &&
1477 (tcp->parent->flags & TCB_SUSPENDED) &&
1478 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1479 error = resume(tcp->parent);
1480 ++resumed;
1481 }
1482#ifdef TCB_CLONE_THREAD
1483 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1484 /* Some other threads of our parent are waiting too. */
1485 unsigned int i;
1486
1487 /* Resume all the threads that were waiting for this PID. */
1488 for (i = 0; i < tcbtabsize; i++) {
1489 struct tcb *t = tcbtab[i];
1490 if (t->parent == tcp->parent && t != tcp
1491 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1492 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1493 && t->waitpid == tcp->pid) {
1494 error |= resume (t);
1495 ++resumed;
1496 }
1497 }
1498 if (resumed == 0)
1499 /* Noone was waiting for this PID in particular,
1500 so now we might need to resume some wildcarders. */
1501 for (i = 0; i < tcbtabsize; i++) {
1502 struct tcb *t = tcbtab[i];
1503 if (t->parent == tcp->parent && t != tcp
1504 && ((t->flags
1505 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1506 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1507 && t->waitpid <= 0
1508 ) {
1509 error |= resume (t);
1510 break;
1511 }
1512 }
1513 }
1514#endif
1515
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001516#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517
1518 if (!qflag)
1519 fprintf(stderr, "Process %u detached\n", tcp->pid);
1520
1521 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001522
1523#ifdef LINUX
1524 if (zombie != NULL)
1525 error = detach(zombie) || error;
1526#endif
1527
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528 return error;
1529}
1530
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001531#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532
1533static void
1534reaper(sig)
1535int sig;
1536{
1537 int pid;
1538 int status;
1539
1540 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1541#if 0
1542 struct tcb *tcp;
1543
1544 tcp = pid2tcb(pid);
1545 if (tcp)
1546 droptcb(tcp);
1547#endif
1548 }
1549}
1550
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001551#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552
1553static void
1554cleanup()
1555{
1556 int i;
1557 struct tcb *tcp;
1558
Roland McGrathee9d4352002-12-18 04:16:10 +00001559 for (i = 0; i < tcbtabsize; i++) {
1560 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 if (!(tcp->flags & TCB_INUSE))
1562 continue;
1563 if (debug)
1564 fprintf(stderr,
1565 "cleanup: looking at pid %u\n", tcp->pid);
1566 if (tcp_last &&
1567 (!outfname || followfork < 2 || tcp_last == tcp)) {
1568 tprintf(" <unfinished ...>\n");
1569 tcp_last = NULL;
1570 }
1571 if (tcp->flags & TCB_ATTACHED)
1572 detach(tcp, 0);
1573 else {
1574 kill(tcp->pid, SIGCONT);
1575 kill(tcp->pid, SIGTERM);
1576 }
1577 }
1578 if (cflag)
1579 call_summary(outf);
1580}
1581
1582static void
1583interrupt(sig)
1584int sig;
1585{
1586 interrupted = 1;
1587}
1588
1589#ifndef HAVE_STRERROR
1590
Roland McGrath6d2b3492002-12-30 00:51:30 +00001591#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592extern int sys_nerr;
1593extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001594#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001595
1596const char *
1597strerror(errno)
1598int errno;
1599{
1600 static char buf[64];
1601
1602 if (errno < 1 || errno >= sys_nerr) {
1603 sprintf(buf, "Unknown error %d", errno);
1604 return buf;
1605 }
1606 return sys_errlist[errno];
1607}
1608
1609#endif /* HAVE_STERRROR */
1610
1611#ifndef HAVE_STRSIGNAL
1612
Roland McGrath8f474e02003-01-14 07:53:33 +00001613#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001614extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001616#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1617extern char *_sys_siglist[];
1618#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619
1620const char *
1621strsignal(sig)
1622int sig;
1623{
1624 static char buf[64];
1625
1626 if (sig < 1 || sig >= NSIG) {
1627 sprintf(buf, "Unknown signal %d", sig);
1628 return buf;
1629 }
1630#ifdef HAVE__SYS_SIGLIST
1631 return _sys_siglist[sig];
1632#else
1633 return sys_siglist[sig];
1634#endif
1635}
1636
1637#endif /* HAVE_STRSIGNAL */
1638
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001639#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640
1641static void
1642rebuild_pollv()
1643{
1644 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645
Roland McGrathee9d4352002-12-18 04:16:10 +00001646 if (pollv != NULL)
1647 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001648 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001649 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001650 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001651 exit(1);
1652 }
1653
Roland McGrathca16be82003-01-10 19:55:28 +00001654 for (i = j = 0; i < tcbtabsize; i++) {
1655 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656 if (!(tcp->flags & TCB_INUSE))
1657 continue;
1658 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001659 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660 j++;
1661 }
1662 if (j != nprocs) {
1663 fprintf(stderr, "strace: proc miscount\n");
1664 exit(1);
1665 }
1666}
1667
1668#ifndef HAVE_POLLABLE_PROCFS
1669
1670static void
1671proc_poll_open()
1672{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673 int i;
1674
1675 if (pipe(proc_poll_pipe) < 0) {
1676 perror("pipe");
1677 exit(1);
1678 }
1679 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001680 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 exit(1);
1682 }
1683 }
1684}
1685
1686static int
1687proc_poll(pollv, nfds, timeout)
1688struct pollfd *pollv;
1689int nfds;
1690int timeout;
1691{
1692 int i;
1693 int n;
1694 struct proc_pollfd pollinfo;
1695
1696 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1697 return n;
1698 if (n != sizeof(struct proc_pollfd)) {
1699 fprintf(stderr, "panic: short read: %d\n", n);
1700 exit(1);
1701 }
1702 for (i = 0; i < nprocs; i++) {
1703 if (pollv[i].fd == pollinfo.fd)
1704 pollv[i].revents = pollinfo.revents;
1705 else
1706 pollv[i].revents = 0;
1707 }
1708 poller_pid = pollinfo.pid;
1709 return 1;
1710}
1711
1712static void
1713wakeup_handler(sig)
1714int sig;
1715{
1716}
1717
1718static void
1719proc_poller(pfd)
1720int pfd;
1721{
1722 struct proc_pollfd pollinfo;
1723 struct sigaction sa;
1724 sigset_t blocked_set, empty_set;
1725 int i;
1726 int n;
1727 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001728#ifdef FREEBSD
1729 struct procfs_status pfs;
1730#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731
1732 switch (fork()) {
1733 case -1:
1734 perror("fork");
1735 _exit(0);
1736 case 0:
1737 break;
1738 default:
1739 return;
1740 }
1741
1742 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1743 sa.sa_flags = 0;
1744 sigemptyset(&sa.sa_mask);
1745 sigaction(SIGHUP, &sa, NULL);
1746 sigaction(SIGINT, &sa, NULL);
1747 sigaction(SIGQUIT, &sa, NULL);
1748 sigaction(SIGPIPE, &sa, NULL);
1749 sigaction(SIGTERM, &sa, NULL);
1750 sa.sa_handler = wakeup_handler;
1751 sigaction(SIGUSR1, &sa, NULL);
1752 sigemptyset(&blocked_set);
1753 sigaddset(&blocked_set, SIGUSR1);
1754 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1755 sigemptyset(&empty_set);
1756
1757 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1758 perror("getrlimit(RLIMIT_NOFILE, ...)");
1759 _exit(0);
1760 }
1761 n = rl.rlim_cur;
1762 for (i = 0; i < n; i++) {
1763 if (i != pfd && i != proc_poll_pipe[1])
1764 close(i);
1765 }
1766
1767 pollinfo.fd = pfd;
1768 pollinfo.pid = getpid();
1769 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001770#ifndef FREEBSD
1771 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1772#else /* FREEBSD */
1773 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1774#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001775 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 switch (errno) {
1777 case EINTR:
1778 continue;
1779 case EBADF:
1780 pollinfo.revents = POLLERR;
1781 break;
1782 case ENOENT:
1783 pollinfo.revents = POLLHUP;
1784 break;
1785 default:
1786 perror("proc_poller: PIOCWSTOP");
1787 }
1788 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1789 _exit(0);
1790 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001791 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1793 sigsuspend(&empty_set);
1794 }
1795}
1796
1797#endif /* !HAVE_POLLABLE_PROCFS */
1798
1799static int
1800choose_pfd()
1801{
1802 int i, j;
1803 struct tcb *tcp;
1804
1805 static int last;
1806
1807 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001808 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 /*
1810 * The previous process is ready to run again. We'll
1811 * let it do so if it is currently in a syscall. This
1812 * heuristic improves the readability of the trace.
1813 */
1814 tcp = pfd2tcb(pollv[last].fd);
1815 if (tcp && (tcp->flags & TCB_INSYSCALL))
1816 return pollv[last].fd;
1817 }
1818
1819 for (i = 0; i < nprocs; i++) {
1820 /* Let competing children run round robin. */
1821 j = (i + last + 1) % nprocs;
1822 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1823 tcp = pfd2tcb(pollv[j].fd);
1824 if (!tcp) {
1825 fprintf(stderr, "strace: lost proc\n");
1826 exit(1);
1827 }
1828 droptcb(tcp);
1829 return -1;
1830 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001831 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832 last = j;
1833 return pollv[j].fd;
1834 }
1835 }
1836 fprintf(stderr, "strace: nothing ready\n");
1837 exit(1);
1838}
1839
1840static int
1841trace()
1842{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001843#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001844 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001845#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846 struct tcb *tcp;
1847 int pfd;
1848 int what;
1849 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001850 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851
1852 for (;;) {
1853 if (interactive)
1854 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1855
1856 if (nprocs == 0)
1857 break;
1858
1859 switch (nprocs) {
1860 case 1:
1861#ifndef HAVE_POLLABLE_PROCFS
1862 if (proc_poll_pipe[0] == -1) {
1863#endif
1864 tcp = pid2tcb(0);
1865 if (!tcp)
1866 continue;
1867 pfd = tcp->pfd;
1868 if (pfd == -1)
1869 continue;
1870 break;
1871#ifndef HAVE_POLLABLE_PROCFS
1872 }
1873 /* fall through ... */
1874#endif /* !HAVE_POLLABLE_PROCFS */
1875 default:
1876#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001877#ifdef POLL_HACK
1878 /* On some systems (e.g. UnixWare) we get too much ugly
1879 "unfinished..." stuff when multiple proceses are in
1880 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001881
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001882 if (in_syscall) {
1883 struct pollfd pv;
1884 tcp = in_syscall;
1885 in_syscall = NULL;
1886 pv.fd = tcp->pfd;
1887 pv.events = POLLWANT;
1888 if ((what = poll (&pv, 1, 1)) < 0) {
1889 if (interrupted)
1890 return 0;
1891 continue;
1892 }
1893 else if (what == 1 && pv.revents & POLLWANT) {
1894 goto FOUND;
1895 }
1896 }
1897#endif
1898
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 if (poll(pollv, nprocs, INFTIM) < 0) {
1900 if (interrupted)
1901 return 0;
1902 continue;
1903 }
1904#else /* !HAVE_POLLABLE_PROCFS */
1905 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1906 if (interrupted)
1907 return 0;
1908 continue;
1909 }
1910#endif /* !HAVE_POLLABLE_PROCFS */
1911 pfd = choose_pfd();
1912 if (pfd == -1)
1913 continue;
1914 break;
1915 }
1916
1917 /* Look up `pfd' in our table. */
1918 if ((tcp = pfd2tcb(pfd)) == NULL) {
1919 fprintf(stderr, "unknown pfd: %u\n", pfd);
1920 exit(1);
1921 }
John Hughesb6643082002-05-23 11:02:22 +00001922#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001923 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001924#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001925 /* Get the status of the process. */
1926 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001927#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001928 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001929#else /* FREEBSD */
1930 /* Thanks to some scheduling mystery, the first poller
1931 sometimes waits for the already processed end of fork
1932 event. Doing a non blocking poll here solves the problem. */
1933 if (proc_poll_pipe[0] != -1)
1934 ioctl_result = IOCTL_STATUS (tcp);
1935 else
1936 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001937#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 ioctl_errno = errno;
1939#ifndef HAVE_POLLABLE_PROCFS
1940 if (proc_poll_pipe[0] != -1) {
1941 if (ioctl_result < 0)
1942 kill(poller_pid, SIGKILL);
1943 else
1944 kill(poller_pid, SIGUSR1);
1945 }
1946#endif /* !HAVE_POLLABLE_PROCFS */
1947 }
1948 if (interrupted)
1949 return 0;
1950
1951 if (interactive)
1952 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1953
1954 if (ioctl_result < 0) {
1955 /* Find out what happened if it failed. */
1956 switch (ioctl_errno) {
1957 case EINTR:
1958 case EBADF:
1959 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001960#ifdef FREEBSD
1961 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00001962#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001963 case ENOENT:
1964 droptcb(tcp);
1965 continue;
1966 default:
1967 perror("PIOCWSTOP");
1968 exit(1);
1969 }
1970 }
1971
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001972#ifdef FREEBSD
1973 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1974 /* discard first event for a syscall we never entered */
1975 IOCTL (tcp->pfd, PIOCRUN, 0);
1976 continue;
1977 }
Roland McGrath553a6092002-12-16 20:40:39 +00001978#endif
1979
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980 /* clear the just started flag */
1981 tcp->flags &= ~TCB_STARTUP;
1982
1983 /* set current output file */
1984 outf = tcp->outf;
1985
1986 if (cflag) {
1987 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001988#ifdef FREEBSD
1989 char buf[1024];
1990 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001991
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001992 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1993 buf[len] = '\0';
1994 sscanf(buf,
1995 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1996 &stime.tv_sec, &stime.tv_usec);
1997 } else
1998 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00001999#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2001 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002002#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2004 tcp->stime = stime;
2005 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002006 what = tcp->status.PR_WHAT;
2007 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002008#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002010 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2011 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 if (trace_syscall(tcp) < 0) {
2013 fprintf(stderr, "syscall trouble\n");
2014 exit(1);
2015 }
2016 }
2017 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002018#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002020#ifdef POLL_HACK
2021 in_syscall = tcp;
2022#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002023 case PR_SYSEXIT:
2024 if (trace_syscall(tcp) < 0) {
2025 fprintf(stderr, "syscall trouble\n");
2026 exit(1);
2027 }
2028 break;
2029 case PR_SIGNALLED:
2030 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2031 printleader(tcp);
2032 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002033 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002035#ifdef PR_INFO
2036 if (tcp->status.PR_INFO.si_signo == what) {
2037 printleader(tcp);
2038 tprintf(" siginfo=");
2039 printsiginfo(&tcp->status.PR_INFO, 1);
2040 printtrailer(tcp);
2041 }
2042#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002043 }
2044 break;
2045 case PR_FAULTED:
2046 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2047 printleader(tcp);
2048 tprintf("=== FAULT %d ===", what);
2049 printtrailer(tcp);
2050 }
2051 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002052#ifdef FREEBSD
2053 case 0: /* handle case we polled for nothing */
2054 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002055#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058 exit(1);
2059 break;
2060 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002061 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002062#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002063 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002064#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002065 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002066#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067 perror("PIOCRUN");
2068 exit(1);
2069 }
2070 }
2071 return 0;
2072}
2073
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002074#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002075
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002076#ifdef TCB_GROUP_EXITING
2077/* Handle an exit detach or death signal that is taking all the
2078 related clone threads with it. This is called in three circumstances:
2079 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2080 SIG == 0 Continuing TCP will perform an exit_group syscall.
2081 SIG == other Continuing TCP with SIG will kill the process.
2082*/
2083static int
2084handle_group_exit(struct tcb *tcp, int sig)
2085{
2086 /* We need to locate our records of all the clone threads
2087 related to TCP, either its children or siblings. */
2088 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2089 ? tcp->parent
2090 : tcp->nclone_detached > 0
2091 ? tcp : NULL);
2092
2093 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002094 if (leader != NULL && leader != tcp &&
2095 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002096 fprintf(stderr,
2097 "PANIC: handle_group_exit: %d leader %d\n",
2098 tcp->pid, leader ? leader->pid : -1);
Roland McGratha08a97e2005-08-03 11:23:46 +00002099 detach(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002100 }
2101 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002102 /* Mark that we are taking the process down. */
2103 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002104 if (tcp->flags & TCB_ATTACHED) {
Roland McGrath00dc13f2004-10-20 02:04:15 +00002105 if (leader != NULL && leader != tcp) {
2106 if (leader->flags & TCB_ATTACHED) {
2107 /* We need to detach the leader so
2108 that the process death will be
2109 reported to its real parent.
2110 But we kill it first to prevent
2111 it doing anything before we kill
2112 the whole process in a moment.
2113 We can use PTRACE_KILL on a
2114 thread that's not already
2115 stopped. Then the value we pass
2116 in PTRACE_DETACH just sets the
2117 death signal reported to the
2118 real parent. */
2119 ptrace(PTRACE_KILL, leader->pid, 0, 0);
2120 if (debug)
2121 fprintf(stderr,
2122 " [%d exit %d kills %d]\n",
2123 tcp->pid, sig, leader->pid);
2124 detach(leader, sig);
2125 }
2126 else
2127 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002128 }
2129 detach(tcp, sig);
2130 }
2131 else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2132 perror("strace: ptrace(PTRACE_CONT, ...)");
2133 cleanup();
2134 return -1;
2135 }
2136 else {
Roland McGrath05690952004-10-20 01:00:27 +00002137 if (leader != NULL)
2138 leader->flags |= TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002139 if (leader != NULL && leader != tcp)
2140 droptcb(tcp);
2141 /* The leader will report to us as parent now,
2142 and then we'll get to the SIG==-1 case. */
2143 return 0;
2144 }
2145 }
2146
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002147 return 0;
2148}
2149#endif
2150
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002151static int
2152trace()
2153{
2154 int pid;
2155 int wait_errno;
2156 int status;
2157 struct tcb *tcp;
2158#ifdef LINUX
2159 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002160#ifdef __WALL
2161 static int wait4_options = __WALL;
2162#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163#endif /* LINUX */
2164
2165 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002166 if (interrupted)
2167 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168 if (interactive)
2169 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2170#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002171#ifdef __WALL
2172 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002173 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002174 /* this kernel does not support __WALL */
2175 wait4_options &= ~__WALL;
2176 errno = 0;
2177 pid = wait4(-1, &status, wait4_options,
2178 cflag ? &ru : NULL);
2179 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002180 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002181 /* most likely a "cloned" process */
2182 pid = wait4(-1, &status, __WCLONE,
2183 cflag ? &ru : NULL);
2184 if (pid == -1) {
2185 fprintf(stderr, "strace: clone wait4 "
2186 "failed: %s\n", strerror(errno));
2187 }
2188 }
2189#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002191#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192#endif /* LINUX */
2193#ifdef SUNOS4
2194 pid = wait(&status);
2195#endif /* SUNOS4 */
2196 wait_errno = errno;
2197 if (interactive)
2198 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2199
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 if (pid == -1) {
2201 switch (wait_errno) {
2202 case EINTR:
2203 continue;
2204 case ECHILD:
2205 /*
2206 * We would like to verify this case
2207 * but sometimes a race in Solbourne's
2208 * version of SunOS sometimes reports
2209 * ECHILD before sending us SIGCHILD.
2210 */
2211#if 0
2212 if (nprocs == 0)
2213 return 0;
2214 fprintf(stderr, "strace: proc miscount\n");
2215 exit(1);
2216#endif
2217 return 0;
2218 default:
2219 errno = wait_errno;
2220 perror("strace: wait");
2221 return -1;
2222 }
2223 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002224 if (pid == popen_pid) {
2225 if (WIFEXITED(status) || WIFSIGNALED(status))
2226 popen_pid = -1;
2227 continue;
2228 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 if (debug)
2230 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2231
2232 /* Look up `pid' in our table. */
2233 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002234#ifdef LINUX
2235 if (followfork || followvfork) {
2236 /* This is needed to go with the CLONE_PTRACE
2237 changes in process.c/util.c: we might see
2238 the child's initial trap before we see the
2239 parent return from the clone syscall.
2240 Leave the child suspended until the parent
2241 returns from its system call. Only then
2242 will we have the association of parent and
2243 child so that we know how to do clearbpt
2244 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002245 if (nprocs == tcbtabsize &&
2246 expand_tcbtab())
2247 tcp = NULL;
2248 else
2249 tcp = alloctcb(pid);
2250 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002251 kill(pid, SIGKILL); /* XXX */
2252 return 0;
2253 }
2254 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002255 if (!qflag)
2256 fprintf(stderr, "\
2257Process %d attached (waiting for parent)\n",
2258 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002259 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002260 else
2261 /* This can happen if a clone call used
2262 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002263#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002264 {
2265 fprintf(stderr, "unknown pid: %u\n", pid);
2266 if (WIFSTOPPED(status))
2267 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2268 exit(1);
2269 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002270 }
2271 /* set current output file */
2272 outf = tcp->outf;
2273 if (cflag) {
2274#ifdef LINUX
2275 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2276 tcp->stime = ru.ru_stime;
2277#endif /* !LINUX */
2278 }
2279
2280 if (tcp->flags & TCB_SUSPENDED) {
2281 /*
2282 * Apparently, doing any ptrace() call on a stopped
2283 * process, provokes the kernel to report the process
2284 * status again on a subsequent wait(), even if the
2285 * process has not been actually restarted.
2286 * Since we have inspected the arguments of suspended
2287 * processes we end up here testing for this case.
2288 */
2289 continue;
2290 }
2291 if (WIFSIGNALED(status)) {
2292 if (!cflag
2293 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2294 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002295 tprintf("+++ killed by %s %s+++",
2296 signame(WTERMSIG(status)),
2297#ifdef WCOREDUMP
2298 WCOREDUMP(status) ? "(core dumped) " :
2299#endif
2300 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002301 printtrailer(tcp);
2302 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002303#ifdef TCB_GROUP_EXITING
2304 handle_group_exit(tcp, -1);
2305#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002307#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 continue;
2309 }
2310 if (WIFEXITED(status)) {
2311 if (debug)
2312 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002313 if ((tcp->flags & TCB_ATTACHED)
2314#ifdef TCB_GROUP_EXITING
2315 && !(tcp->parent && (tcp->parent->flags &
2316 TCB_GROUP_EXITING))
2317#endif
2318 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002319 fprintf(stderr,
2320 "PANIC: attached pid %u exited\n",
2321 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002322 if (tcp == tcp_last) {
2323 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2324 == TCB_INSYSCALL)
2325 tprintf(" <unfinished ... exit status %d>\n",
2326 WEXITSTATUS(status));
2327 tcp_last = NULL;
2328 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002329#ifdef TCB_GROUP_EXITING
2330 handle_group_exit(tcp, -1);
2331#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002332 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002333#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 continue;
2335 }
2336 if (!WIFSTOPPED(status)) {
2337 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2338 droptcb(tcp);
2339 continue;
2340 }
2341 if (debug)
2342 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002343 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002344
Roland McGrath02203312007-06-11 22:06:31 +00002345 /*
2346 * Interestingly, the process may stop
2347 * with STOPSIG equal to some other signal
2348 * than SIGSTOP if we happend to attach
2349 * just before the process takes a signal.
2350 */
2351 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352 /*
2353 * This flag is there to keep us in sync.
2354 * Next time this process stops it should
2355 * really be entering a system call.
2356 */
2357 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002358 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002359 /*
2360 * One example is a breakpoint inherited from
2361 * parent through fork ().
2362 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2364 droptcb(tcp);
2365 cleanup();
2366 return -1;
2367 }
2368 }
2369 goto tracing;
2370 }
2371
2372 if (WSTOPSIG(status) != SIGTRAP) {
2373 if (WSTOPSIG(status) == SIGSTOP &&
2374 (tcp->flags & TCB_SIGTRAPPED)) {
2375 /*
2376 * Trapped attempt to block SIGTRAP
2377 * Hope we are back in control now.
2378 */
2379 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2380 if (ptrace(PTRACE_SYSCALL,
2381 pid, (char *) 1, 0) < 0) {
2382 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2383 cleanup();
2384 return -1;
2385 }
2386 continue;
2387 }
2388 if (!cflag
2389 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002390 unsigned long addr = 0, pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002391#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002392# define PSR_RI 41
2393 struct siginfo si;
2394 unsigned long psr;
2395
2396 upeek(pid, PT_CR_IPSR, &psr);
2397 upeek(pid, PT_CR_IIP, &pc);
2398
2399 pc += (psr >> PSR_RI) & 0x3;
2400 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2401 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002402#elif defined PTRACE_GETSIGINFO
2403 if (WSTOPSIG(status) == SIGSEGV ||
2404 WSTOPSIG(status) == SIGBUS) {
2405 siginfo_t si;
2406 if (ptrace(PTRACE_GETSIGINFO, pid,
2407 0, &si) == 0)
2408 addr = (unsigned long)
2409 si.si_addr;
2410 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002411#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002412 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002413 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002414 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002415 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002416 printtrailer(tcp);
2417 }
Roland McGrath05690952004-10-20 01:00:27 +00002418 if (((tcp->flags & TCB_ATTACHED) ||
2419 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002421#ifdef TCB_GROUP_EXITING
2422 handle_group_exit(tcp, WSTOPSIG(status));
2423#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002425#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002426 continue;
2427 }
2428 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
2429 WSTOPSIG(status)) < 0) {
2430 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2431 cleanup();
2432 return -1;
2433 }
2434 tcp->flags &= ~TCB_SUSPENDED;
2435 continue;
2436 }
Roland McGrath02203312007-06-11 22:06:31 +00002437 /* we handled the STATUS, we are permitted to interrupt now. */
2438 if (interrupted)
2439 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002440 if (trace_syscall(tcp) < 0) {
2441 if (tcp->flags & TCB_ATTACHED)
2442 detach(tcp, 0);
2443 else {
2444 ptrace(PTRACE_KILL,
2445 tcp->pid, (char *) 1, SIGTERM);
2446 droptcb(tcp);
2447 }
2448 continue;
2449 }
2450 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002451#ifdef TCB_GROUP_EXITING
2452 if (tcp->flags & TCB_GROUP_EXITING) {
2453 if (handle_group_exit(tcp, 0) < 0)
2454 return -1;
2455 continue;
2456 }
2457#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002458 if (tcp->flags & TCB_ATTACHED)
2459 detach(tcp, 0);
2460 else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
2461 perror("strace: ptrace(PTRACE_CONT, ...)");
2462 cleanup();
2463 return -1;
2464 }
2465 continue;
2466 }
2467 if (tcp->flags & TCB_SUSPENDED) {
2468 if (!qflag)
2469 fprintf(stderr, "Process %u suspended\n", pid);
2470 continue;
2471 }
2472 tracing:
2473 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
2474 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
2475 cleanup();
2476 return -1;
2477 }
2478 }
2479 return 0;
2480}
2481
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002482#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002483
2484static int curcol;
2485
2486#ifdef __STDC__
2487#include <stdarg.h>
2488#define VA_START(a, b) va_start(a, b)
2489#else
2490#include <varargs.h>
2491#define VA_START(a, b) va_start(a)
2492#endif
2493
2494void
2495#ifdef __STDC__
2496tprintf(const char *fmt, ...)
2497#else
2498tprintf(fmt, va_alist)
2499char *fmt;
2500va_dcl
2501#endif
2502{
2503 va_list args;
2504
2505 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002506 if (outf) {
2507 int n = vfprintf(outf, fmt, args);
2508 if (n < 0 && outf != stderr)
2509 perror(outfname == NULL
2510 ? "<writing to pipe>" : outfname);
2511 else
2512 curcol += n;
2513 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002514 va_end(args);
2515 return;
2516}
2517
2518void
2519printleader(tcp)
2520struct tcb *tcp;
2521{
2522 if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
2523 tcp_last->flags |= TCB_REPRINT;
2524 tprintf(" <unfinished ...>\n");
2525 }
2526 curcol = 0;
2527 if ((followfork == 1 || pflag_seen > 1) && outfname)
2528 tprintf("%-5d ", tcp->pid);
2529 else if (nprocs > 1 && !outfname)
2530 tprintf("[pid %5u] ", tcp->pid);
2531 if (tflag) {
2532 char str[sizeof("HH:MM:SS")];
2533 struct timeval tv, dtv;
2534 static struct timeval otv;
2535
2536 gettimeofday(&tv, NULL);
2537 if (rflag) {
2538 if (otv.tv_sec == 0)
2539 otv = tv;
2540 tv_sub(&dtv, &tv, &otv);
2541 tprintf("%6ld.%06ld ",
2542 (long) dtv.tv_sec, (long) dtv.tv_usec);
2543 otv = tv;
2544 }
2545 else if (tflag > 2) {
2546 tprintf("%ld.%06ld ",
2547 (long) tv.tv_sec, (long) tv.tv_usec);
2548 }
2549 else {
2550 time_t local = tv.tv_sec;
2551 strftime(str, sizeof(str), "%T", localtime(&local));
2552 if (tflag > 1)
2553 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2554 else
2555 tprintf("%s ", str);
2556 }
2557 }
2558 if (iflag)
2559 printcall(tcp);
2560}
2561
2562void
2563tabto(col)
2564int col;
2565{
2566 if (curcol < col)
2567 tprintf("%*s", col - curcol, "");
2568}
2569
2570void
2571printtrailer(tcp)
2572struct tcb *tcp;
2573{
2574 tprintf("\n");
2575 tcp_last = NULL;
2576}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002577
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002578#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002579
2580int mp_ioctl (int fd, int cmd, void *arg, int size) {
2581
2582 struct iovec iov[2];
2583 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002584
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002585 iov[0].iov_base = &cmd;
2586 iov[0].iov_len = sizeof cmd;
2587 if (arg) {
2588 ++n;
2589 iov[1].iov_base = arg;
2590 iov[1].iov_len = size;
2591 }
Roland McGrath553a6092002-12-16 20:40:39 +00002592
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002593 return writev (fd, iov, n);
2594}
2595
2596#endif