blob: 5f5076077317b2dd665e051335513cb617c76297 [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. Levina6809652008-11-10 17:14:58 +000088static int exit_code = 0;
89static int strace_child = 0;
90
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000091static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092uid_t run_uid;
93gid_t run_gid;
94
95int acolumn = DEFAULT_ACOLUMN;
96int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000097static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098FILE *outf;
Roland McGrathee9d4352002-12-18 04:16:10 +000099struct tcb **tcbtab;
100unsigned int nprocs, tcbtabsize;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102extern char **environ;
103
Roland McGrath0a463882007-07-05 18:43:16 +0000104static int detach P((struct tcb *tcp, int sig));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105static int trace P((void));
106static void cleanup P((void));
107static void interrupt P((int sig));
108static sigset_t empty_set, blocked_set;
109
110#ifdef HAVE_SIG_ATOMIC_T
111static volatile sig_atomic_t interrupted;
112#else /* !HAVE_SIG_ATOMIC_T */
113#ifdef __STDC__
114static volatile int interrupted;
115#else /* !__STDC__ */
116static int interrupted;
117#endif /* !__STDC__ */
118#endif /* !HAVE_SIG_ATOMIC_T */
119
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000120#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
122static struct tcb *pfd2tcb P((int pfd));
123static void reaper P((int sig));
124static void rebuild_pollv P((void));
Roland McGrathee9d4352002-12-18 04:16:10 +0000125static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126
127#ifndef HAVE_POLLABLE_PROCFS
128
129static void proc_poll_open P((void));
130static void proc_poller P((int pfd));
131
132struct proc_pollfd {
133 int fd;
134 int revents;
135 int pid;
136};
137
138static int poller_pid;
139static int proc_poll_pipe[2] = { -1, -1 };
140
141#endif /* !HAVE_POLLABLE_PROCFS */
142
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000143#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000144#define POLLWANT POLLWRNORM
145#else
146#define POLLWANT POLLPRI
147#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000148#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149
150static void
151usage(ofp, exitval)
152FILE *ofp;
153int exitval;
154{
155 fprintf(ofp, "\
156usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000157 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
158 [command [arg ...]]\n\
159 or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
160 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161-c -- count time, calls, and errors for each syscall and report summary\n\
162-f -- follow forks, -ff -- with output into separate files\n\
163-F -- attempt to follow vforks, -h -- print help message\n\
164-i -- print instruction pointer at time of syscall\n\
165-q -- suppress messages about attaching, detaching, etc.\n\
166-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
167-T -- print time spent in each syscall, -V -- print version\n\
168-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
169-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
170-a column -- alignment COLUMN for printing syscall results (default %d)\n\
171-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
172 options: trace, abbrev, verbose, raw, signal, read, or write\n\
173-o file -- send trace output to FILE instead of stderr\n\
174-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
175-p pid -- trace process with process id PID, may be repeated\n\
176-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
177-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
178-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000179-E var=val -- put var=val in the environment for command\n\
180-E var -- remove var from the environment for command\n\
181" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000182-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000183 */
184, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185 exit(exitval);
186}
187
188#ifdef SVR4
189#ifdef MIPS
190void
191foobar()
192{
193}
194#endif /* MIPS */
195#endif /* SVR4 */
196
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000197static int
198set_cloexec_flag(int fd)
199{
200 int flags, newflags;
201
202 if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
203 {
204 fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
205 progname, strerror(errno));
206 return -1;
207 }
208
209 newflags = flags | FD_CLOEXEC;
210 if (flags == newflags)
211 return 0;
212
213 if (fcntl(fd, F_SETFD, newflags) < 0)
214 {
215 fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
216 progname, strerror(errno));
217 return -1;
218 }
219
220 return 0;
221}
222
223/*
224 * When strace is setuid executable, we have to swap uids
225 * before and after filesystem and process management operations.
226 */
227static void
228swap_uid(void)
229{
230#ifndef SVR4
231 int euid = geteuid(), uid = getuid();
232
233 if (euid != uid && setreuid(euid, uid) < 0)
234 {
235 fprintf(stderr, "%s: setreuid: %s\n",
236 progname, strerror(errno));
237 exit(1);
238 }
239#endif
240}
241
Roland McGrath4bfa6262007-07-05 20:03:16 +0000242#if _LFS64_LARGEFILE
243# define fopen_for_output fopen64
244#else
245# define fopen_for_output fopen
246#endif
247
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000248static FILE *
249strace_fopen(const char *path, const char *mode)
250{
251 FILE *fp;
252
253 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000254 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000255 fprintf(stderr, "%s: can't fopen '%s': %s\n",
256 progname, path, strerror(errno));
257 swap_uid();
258 if (fp && set_cloexec_flag(fileno(fp)) < 0)
259 {
260 fclose(fp);
261 fp = NULL;
262 }
263 return fp;
264}
265
266static int popen_pid = -1;
267
268#ifndef _PATH_BSHELL
269# define _PATH_BSHELL "/bin/sh"
270#endif
271
272/*
273 * We cannot use standard popen(3) here because we have to distinguish
274 * popen child process from other processes we trace, and standard popen(3)
275 * does not export its child's pid.
276 */
277static FILE *
278strace_popen(const char *command)
279{
280 int fds[2];
281
282 swap_uid();
283 if (pipe(fds) < 0)
284 {
285 fprintf(stderr, "%s: pipe: %s\n",
286 progname, strerror(errno));
287 swap_uid();
288 return NULL;
289 }
290
291 if (set_cloexec_flag(fds[1]) < 0)
292 {
293 close(fds[0]);
294 close(fds[1]);
295 swap_uid();
296 return NULL;
297 }
298
299 if ((popen_pid = fork()) == -1)
300 {
301 fprintf(stderr, "%s: fork: %s\n",
302 progname, strerror(errno));
303 close(fds[0]);
304 close(fds[1]);
305 swap_uid();
306 return NULL;
307 }
308
309 if (popen_pid)
310 {
311 /* parent */
312 close(fds[0]);
313 swap_uid();
314 return fdopen(fds[1], "w");
315 } else
316 {
317 /* child */
318 close(fds[1]);
319 if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
320 {
321 fprintf(stderr, "%s: dup2: %s\n",
322 progname, strerror(errno));
323 _exit(1);
324 }
325 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
326 fprintf(stderr, "%s: execl: %s: %s\n",
327 progname, _PATH_BSHELL, strerror(errno));
328 _exit(1);
329 }
330}
331
332static int
333newoutf(struct tcb *tcp)
334{
335 if (outfname && followfork > 1) {
336 char name[MAXPATHLEN];
337 FILE *fp;
338
339 sprintf(name, "%s.%u", outfname, tcp->pid);
340 if ((fp = strace_fopen(name, "w")) == NULL)
341 return -1;
342 tcp->outf = fp;
343 }
344 return 0;
345}
346
Roland McGrath02203312007-06-11 22:06:31 +0000347static void
348startup_attach(void)
349{
350 int tcbi;
351 struct tcb *tcp;
352
353 /*
354 * Block user interruptions as we would leave the traced
355 * process stopped (process state T) if we would terminate in
356 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
357 * We rely on cleanup () from this point on.
358 */
359 if (interactive)
360 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
361
362 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
363 tcp = tcbtab[tcbi];
364 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
365 continue;
366#ifdef LINUX
367 if (tcp->flags & TCB_CLONE_THREAD)
368 continue;
369#endif
370 /* Reinitialize the output since it may have changed. */
371 tcp->outf = outf;
372 if (newoutf(tcp) < 0)
373 exit(1);
374
375#ifdef USE_PROCFS
376 if (proc_open(tcp, 1) < 0) {
377 fprintf(stderr, "trouble opening proc file\n");
378 droptcb(tcp);
379 continue;
380 }
381#else /* !USE_PROCFS */
382# ifdef LINUX
383 if (followfork) {
384 char procdir[MAXPATHLEN];
385 DIR *dir;
386
387 sprintf(procdir, "/proc/%d/task", tcp->pid);
388 dir = opendir(procdir);
389 if (dir != NULL) {
390 unsigned int ntid = 0, nerr = 0;
391 struct dirent *de;
392 int tid;
393 while ((de = readdir(dir)) != NULL) {
394 if (de->d_fileno == 0 ||
395 de->d_name[0] == '.')
396 continue;
397 tid = atoi(de->d_name);
398 if (tid <= 0)
399 continue;
400 ++ntid;
401 if (ptrace(PTRACE_ATTACH, tid,
402 (char *) 1, 0) < 0)
403 ++nerr;
404 else if (tid != tcbtab[tcbi]->pid) {
405 if (nprocs == tcbtabsize &&
406 expand_tcbtab())
407 tcp = NULL;
408 else
409 tcp = alloctcb(tid);
410 if (tcp == NULL)
411 exit(1);
412 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
413 tcbtab[tcbi]->nchildren++;
414 tcbtab[tcbi]->nclone_threads++;
415 tcbtab[tcbi]->nclone_detached++;
416 tcp->parent = tcbtab[tcbi];
417 }
418 if (interactive) {
419 sigprocmask(SIG_SETMASK, &empty_set, NULL);
420 if (interrupted)
421 return;
422 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
423 }
424 }
425 closedir(dir);
426 if (nerr == ntid) {
427 perror("attach: ptrace(PTRACE_ATTACH, ...)");
428 droptcb(tcp);
429 continue;
430 }
431 if (!qflag) {
432 ntid -= nerr;
433 if (ntid > 1)
434 fprintf(stderr, "\
435Process %u attached with %u threads - interrupt to quit\n",
436 tcp->pid, ntid);
437 else
438 fprintf(stderr, "\
439Process %u attached - interrupt to quit\n",
440 tcp->pid);
441 }
442 continue;
443 }
444 }
445# endif
446 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
447 perror("attach: ptrace(PTRACE_ATTACH, ...)");
448 droptcb(tcp);
449 continue;
450 }
451 /* INTERRUPTED is going to be checked at the top of TRACE. */
452#endif /* !USE_PROCFS */
453 if (!qflag)
454 fprintf(stderr,
455 "Process %u attached - interrupt to quit\n",
456 tcp->pid);
457 }
458
459 if (interactive)
460 sigprocmask(SIG_SETMASK, &empty_set, NULL);
461}
462
463static void
464startup_child (char **argv)
465{
466 struct stat statbuf;
467 const char *filename;
468 char pathname[MAXPATHLEN];
469 int pid = 0;
470 struct tcb *tcp;
471
472 filename = argv[0];
473 if (strchr(filename, '/')) {
474 if (strlen(filename) > sizeof pathname - 1) {
475 errno = ENAMETOOLONG;
476 perror("strace: exec");
477 exit(1);
478 }
479 strcpy(pathname, filename);
480 }
481#ifdef USE_DEBUGGING_EXEC
482 /*
483 * Debuggers customarily check the current directory
484 * first regardless of the path but doing that gives
485 * security geeks a panic attack.
486 */
487 else if (stat(filename, &statbuf) == 0)
488 strcpy(pathname, filename);
489#endif /* USE_DEBUGGING_EXEC */
490 else {
491 char *path;
492 int m, n, len;
493
494 for (path = getenv("PATH"); path && *path; path += m) {
495 if (strchr(path, ':')) {
496 n = strchr(path, ':') - path;
497 m = n + 1;
498 }
499 else
500 m = n = strlen(path);
501 if (n == 0) {
502 if (!getcwd(pathname, MAXPATHLEN))
503 continue;
504 len = strlen(pathname);
505 }
506 else if (n > sizeof pathname - 1)
507 continue;
508 else {
509 strncpy(pathname, path, n);
510 len = n;
511 }
512 if (len && pathname[len - 1] != '/')
513 pathname[len++] = '/';
514 strcpy(pathname + len, filename);
515 if (stat(pathname, &statbuf) == 0 &&
516 /* Accept only regular files
517 with some execute bits set.
518 XXX not perfect, might still fail */
519 S_ISREG(statbuf.st_mode) &&
520 (statbuf.st_mode & 0111))
521 break;
522 }
523 }
524 if (stat(pathname, &statbuf) < 0) {
525 fprintf(stderr, "%s: %s: command not found\n",
526 progname, filename);
527 exit(1);
528 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000529 strace_child = pid = fork();
530 switch (pid) {
Roland McGrath02203312007-06-11 22:06:31 +0000531 case -1:
532 perror("strace: fork");
533 cleanup();
534 exit(1);
535 break;
536 case 0: {
537#ifdef USE_PROCFS
538 if (outf != stderr) close (fileno (outf));
539#ifdef MIPS
540 /* Kludge for SGI, see proc_open for details. */
541 sa.sa_handler = foobar;
542 sa.sa_flags = 0;
543 sigemptyset(&sa.sa_mask);
544 sigaction(SIGINT, &sa, NULL);
545#endif /* MIPS */
546#ifndef FREEBSD
547 pause();
548#else /* FREEBSD */
549 kill(getpid(), SIGSTOP); /* stop HERE */
550#endif /* FREEBSD */
551#else /* !USE_PROCFS */
552 if (outf!=stderr)
553 close(fileno (outf));
554
555 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
556 perror("strace: ptrace(PTRACE_TRACEME, ...)");
557 exit(1);
558 }
559 if (debug)
560 kill(getpid(), SIGSTOP);
561
562 if (username != NULL || geteuid() == 0) {
563 uid_t run_euid = run_uid;
564 gid_t run_egid = run_gid;
565
566 if (statbuf.st_mode & S_ISUID)
567 run_euid = statbuf.st_uid;
568 if (statbuf.st_mode & S_ISGID)
569 run_egid = statbuf.st_gid;
570
571 /*
572 * It is important to set groups before we
573 * lose privileges on setuid.
574 */
575 if (username != NULL) {
576 if (initgroups(username, run_gid) < 0) {
577 perror("initgroups");
578 exit(1);
579 }
580 if (setregid(run_gid, run_egid) < 0) {
581 perror("setregid");
582 exit(1);
583 }
584 if (setreuid(run_uid, run_euid) < 0) {
585 perror("setreuid");
586 exit(1);
587 }
588 }
589 }
590 else
591 setreuid(run_uid, run_uid);
592
593 /*
594 * Induce an immediate stop so that the parent
595 * will resume us with PTRACE_SYSCALL and display
596 * this execve call normally.
597 */
598 kill(getpid(), SIGSTOP);
599#endif /* !USE_PROCFS */
600
601 execv(pathname, argv);
602 perror("strace: exec");
603 _exit(1);
604 break;
605 }
606 default:
607 if ((tcp = alloctcb(pid)) == NULL) {
608 cleanup();
609 exit(1);
610 }
611#ifdef USE_PROCFS
612 if (proc_open(tcp, 0) < 0) {
613 fprintf(stderr, "trouble opening proc file\n");
614 cleanup();
615 exit(1);
616 }
617#endif /* USE_PROCFS */
618 break;
619 }
620}
621
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000622int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000623main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624{
625 extern int optind;
626 extern char *optarg;
627 struct tcb *tcp;
628 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000629 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000630 struct sigaction sa;
631
632 static char buf[BUFSIZ];
633
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000634 progname = argv[0] ? argv[0] : "strace";
635
Roland McGrathee9d4352002-12-18 04:16:10 +0000636 /* Allocate the initial tcbtab. */
637 tcbtabsize = argc; /* Surely enough for all -p args. */
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000638 if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) {
639 fprintf(stderr, "%s: out of memory\n", progname);
640 exit(1);
641 }
642 if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
643 fprintf(stderr, "%s: out of memory\n", progname);
644 exit(1);
645 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000646 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
647 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
648
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649 outf = stderr;
650 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000651 set_sortby(DEFAULT_SORTBY);
652 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653 qualify("trace=all");
654 qualify("abbrev=all");
655 qualify("verbose=all");
656 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000657 while ((c = getopt(argc, argv,
Roland McGrathde6e5332003-01-24 04:31:23 +0000658 "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000659 switch (c) {
660 case 'c':
661 cflag++;
662 dtime++;
663 break;
664 case 'd':
665 debug++;
666 break;
Roland McGrath41c48222008-07-18 00:25:10 +0000667 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000668 optF = 1;
669 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670 case 'f':
671 followfork++;
672 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673 case 'h':
674 usage(stdout, 0);
675 break;
676 case 'i':
677 iflag++;
678 break;
679 case 'q':
680 qflag++;
681 break;
682 case 'r':
683 rflag++;
684 tflag++;
685 break;
686 case 't':
687 tflag++;
688 break;
689 case 'T':
690 dtime++;
691 break;
692 case 'x':
693 xflag++;
694 break;
695 case 'v':
696 qualify("abbrev=none");
697 break;
698 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000699 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700 exit(0);
701 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000702 case 'z':
703 not_failing_only = 1;
704 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 case 'a':
706 acolumn = atoi(optarg);
707 break;
708 case 'e':
709 qualify(optarg);
710 break;
711 case 'o':
712 outfname = strdup(optarg);
713 break;
714 case 'O':
715 set_overhead(atoi(optarg));
716 break;
717 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000718 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 fprintf(stderr, "%s: Invalid process id: %s\n",
720 progname, optarg);
721 break;
722 }
723 if (pid == getpid()) {
Wichert Akkerman54a47671999-10-17 00:57:34 +0000724 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000725 break;
726 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000727 if ((tcp = alloc_tcb(pid, 0)) == NULL) {
Roland McGrathde6e5332003-01-24 04:31:23 +0000728 fprintf(stderr, "%s: out of memory\n",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000729 progname);
730 exit(1);
731 }
732 tcp->flags |= TCB_ATTACHED;
733 pflag_seen++;
734 break;
735 case 's':
736 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +0000737 if (max_strlen < 0) {
738 fprintf(stderr,
739 "%s: invalid -s argument: %s\n",
740 progname, optarg);
741 exit(1);
742 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000743 break;
744 case 'S':
745 set_sortby(optarg);
746 break;
747 case 'u':
748 username = strdup(optarg);
749 break;
Roland McGrathde6e5332003-01-24 04:31:23 +0000750 case 'E':
751 if (putenv(optarg) < 0) {
752 fprintf(stderr, "%s: out of memory\n",
753 progname);
754 exit(1);
755 }
756 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 default:
758 usage(stderr, 1);
759 break;
760 }
761 }
762
Roland McGrathd0c4c0c2006-04-25 07:39:40 +0000763 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +0000764 usage(stderr, 1);
765
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000766 if (!followfork)
767 followfork = optF;
768
Roland McGrathcb9def62006-04-25 07:48:03 +0000769 if (followfork > 1 && cflag) {
770 fprintf(stderr,
771 "%s: -c and -ff are mutually exclusive options\n",
772 progname);
773 exit(1);
774 }
775
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776 /* See if they want to run as another user. */
777 if (username != NULL) {
778 struct passwd *pent;
779
780 if (getuid() != 0 || geteuid() != 0) {
781 fprintf(stderr,
782 "%s: you must be root to use the -u option\n",
783 progname);
784 exit(1);
785 }
786 if ((pent = getpwnam(username)) == NULL) {
787 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +0000788 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789 exit(1);
790 }
791 run_uid = pent->pw_uid;
792 run_gid = pent->pw_gid;
793 }
794 else {
795 run_uid = getuid();
796 run_gid = getgid();
797 }
798
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000799 /* Check if they want to redirect the output. */
800 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +0000801 /* See if they want to pipe the output. */
802 if (outfname[0] == '|' || outfname[0] == '!') {
803 /*
804 * We can't do the <outfname>.PID funny business
805 * when using popen, so prohibit it.
806 */
807 if (followfork > 1) {
808 fprintf(stderr, "\
809%s: piping the output and -ff are mutually exclusive options\n",
810 progname);
811 exit(1);
812 }
813
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000814 if ((outf = strace_popen(outfname + 1)) == NULL)
Roland McGrath37b9a662003-11-07 02:26:54 +0000815 exit(1);
Roland McGrath37b9a662003-11-07 02:26:54 +0000816 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000817 else if (followfork <= 1 &&
818 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000820 }
821
Roland McGrath37b9a662003-11-07 02:26:54 +0000822 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000823 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +0000824 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000825 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +0000827 }
Roland McGrath54cc1c82007-11-03 23:34:11 +0000828 /* Valid states here:
829 optind < argc pflag_seen outfname interactive
830 1 0 0 1
831 0 1 0 1
832 1 0 1 0
833 0 1 1 1
834 */
835
836 /* STARTUP_CHILD must be called before the signal handlers get
837 installed below as they are inherited into the spawned process.
838 Also we do not need to be protected by them as during interruption
839 in the STARTUP_CHILD mode we kill the spawned process anyway. */
840 if (!pflag_seen)
841 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000842
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000843 sigemptyset(&empty_set);
844 sigemptyset(&blocked_set);
845 sa.sa_handler = SIG_IGN;
846 sigemptyset(&sa.sa_mask);
847 sa.sa_flags = 0;
848 sigaction(SIGTTOU, &sa, NULL);
849 sigaction(SIGTTIN, &sa, NULL);
850 if (interactive) {
851 sigaddset(&blocked_set, SIGHUP);
852 sigaddset(&blocked_set, SIGINT);
853 sigaddset(&blocked_set, SIGQUIT);
854 sigaddset(&blocked_set, SIGPIPE);
855 sigaddset(&blocked_set, SIGTERM);
856 sa.sa_handler = interrupt;
857#ifdef SUNOS4
858 /* POSIX signals on sunos4.1 are a little broken. */
859 sa.sa_flags = SA_INTERRUPT;
860#endif /* SUNOS4 */
861 }
862 sigaction(SIGHUP, &sa, NULL);
863 sigaction(SIGINT, &sa, NULL);
864 sigaction(SIGQUIT, &sa, NULL);
865 sigaction(SIGPIPE, &sa, NULL);
866 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000867#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 sa.sa_handler = reaper;
869 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +0000870#else
871 /* Make sure SIGCHLD has the default action so that waitpid
872 definitely works without losing track of children. The user
873 should not have given us a bogus state to inherit, but he might
874 have. Arguably we should detect SIG_IGN here and pass it on
875 to children, but probably noone really needs that. */
876 sa.sa_handler = SIG_DFL;
877 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000878#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879
Roland McGrath02203312007-06-11 22:06:31 +0000880 if (pflag_seen)
881 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +0000882
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883 if (trace() < 0)
884 exit(1);
885 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +0000886 fflush(NULL);
887 if (exit_code > 0xff) {
888 /* Child was killed by a signal, mimic that. */
889 exit_code &= 0xff;
890 signal(exit_code, SIG_DFL);
891 raise(exit_code);
892 /* Paranoia - what if this signal is not fatal?
893 Exit with 128 + signo then. */
894 exit_code += 128;
895 }
896 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897}
898
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000899int
900expand_tcbtab()
901{
902 /* Allocate some more TCBs and expand the table.
903 We don't want to relocate the TCBs because our
904 callers have pointers and it would be a pain.
905 So tcbtab is a table of pointers. Since we never
906 free the TCBs, we allocate a single chunk of many. */
907 struct tcb **newtab = (struct tcb **)
908 realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
909 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
910 sizeof *newtcbs);
911 int i;
912 if (newtab == NULL || newtcbs == NULL) {
913 if (newtab != NULL)
914 free(newtab);
Dmitry V. Levin76860f62006-10-11 22:55:25 +0000915 fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
916 progname);
Roland McGrath7b54a7a2004-06-04 01:50:45 +0000917 return 1;
918 }
919 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
920 newtab[i] = &newtcbs[i - tcbtabsize];
921 tcbtabsize *= 2;
922 tcbtab = newtab;
923
924 return 0;
925}
926
927
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000929alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000930{
931 int i;
932 struct tcb *tcp;
933
Roland McGrathee9d4352002-12-18 04:16:10 +0000934 for (i = 0; i < tcbtabsize; i++) {
935 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936 if ((tcp->flags & TCB_INUSE) == 0) {
937 tcp->pid = pid;
938 tcp->parent = NULL;
939 tcp->nchildren = 0;
Roland McGrath09623452003-05-23 02:27:13 +0000940 tcp->nzombies = 0;
Roland McGrathe85bbfe2003-01-09 06:53:31 +0000941#ifdef TCB_CLONE_THREAD
942 tcp->nclone_threads = tcp->nclone_detached = 0;
943 tcp->nclone_waiting = 0;
944#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 tcp->flags = TCB_INUSE | TCB_STARTUP;
Denys Vlasenko1e3ce322008-12-22 19:14:47 +0000946 tcp->sigtrap80 = SIGTRAP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947 tcp->outf = outf; /* Initialise to current out file */
948 tcp->stime.tv_sec = 0;
949 tcp->stime.tv_usec = 0;
950 tcp->pfd = -1;
951 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000952 if (command_options_parsed)
953 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 return tcp;
955 }
956 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000957 fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 return NULL;
959}
960
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000961#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962int
963proc_open(tcp, attaching)
964struct tcb *tcp;
965int attaching;
966{
967 char proc[32];
968 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000969#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +0000970 int i;
971 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 sigset_t signals;
973 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000974#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975#ifndef HAVE_POLLABLE_PROCFS
976 static int last_pfd;
977#endif
978
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000979#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000980 /* Open the process pseudo-files in /proc. */
981 sprintf(proc, "/proc/%d/ctl", tcp->pid);
982 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 perror("strace: open(\"/proc/...\", ...)");
984 return -1;
985 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000986 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 return -1;
988 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000989 sprintf(proc, "/proc/%d/status", tcp->pid);
990 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
991 perror("strace: open(\"/proc/...\", ...)");
992 return -1;
993 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000994 if (set_cloexec_flag(tcp->pfd_stat) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000995 return -1;
996 }
997 sprintf(proc, "/proc/%d/as", tcp->pid);
998 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
999 perror("strace: open(\"/proc/...\", ...)");
1000 return -1;
1001 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001002 if (set_cloexec_flag(tcp->pfd_as) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001003 return -1;
1004 }
1005#else
1006 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001007#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001008 sprintf(proc, "/proc/%d", tcp->pid);
1009 if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001010#else /* FREEBSD */
1011 sprintf(proc, "/proc/%d/mem", tcp->pid);
1012 if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1013#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001014 perror("strace: open(\"/proc/...\", ...)");
1015 return -1;
1016 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001017 if (set_cloexec_flag(tcp->pfd) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001018 return -1;
1019 }
1020#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001021#ifdef FREEBSD
1022 sprintf(proc, "/proc/%d/regs", tcp->pid);
1023 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1024 perror("strace: open(\"/proc/.../regs\", ...)");
1025 return -1;
1026 }
1027 if (cflag) {
1028 sprintf(proc, "/proc/%d/status", tcp->pid);
1029 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1030 perror("strace: open(\"/proc/.../status\", ...)");
1031 return -1;
1032 }
1033 } else
1034 tcp->pfd_status = -1;
1035#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001036 rebuild_pollv();
1037 if (!attaching) {
1038 /*
1039 * Wait for the child to pause. Because of a race
1040 * condition we have to poll for the event.
1041 */
1042 for (;;) {
1043 if (IOCTL_STATUS (tcp) < 0) {
1044 perror("strace: PIOCSTATUS");
1045 return -1;
1046 }
1047 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001048 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001049 }
1050 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001051#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001052 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001053 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001054 perror("strace: PIOCSTOP");
1055 return -1;
1056 }
Roland McGrath553a6092002-12-16 20:40:39 +00001057#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058#ifdef PIOCSET
1059 /* Set Run-on-Last-Close. */
1060 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 perror("PIOCSET PR_RLC");
1063 return -1;
1064 }
1065 /* Set or Reset Inherit-on-Fork. */
1066 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001067 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 perror("PIOC{SET,RESET} PR_FORK");
1069 return -1;
1070 }
1071#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001072#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1074 perror("PIOCSRLC");
1075 return -1;
1076 }
1077 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1078 perror("PIOC{S,R}FORK");
1079 return -1;
1080 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001081#else /* FREEBSD */
1082 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1083 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1084 perror("PIOCGFL");
1085 return -1;
1086 }
1087 arg &= ~PF_LINGER;
1088 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1089 perror("PIOCSFL");
1090 return -1;
1091 }
1092#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001094#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001095 /* Enable all syscall entries we care about. */
1096 premptyset(&syscalls);
1097 for (i = 1; i < MAX_QUALS; ++i) {
1098 if (i > (sizeof syscalls) * CHAR_BIT) break;
1099 if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
1100 }
1101 praddset (&syscalls, SYS_execve);
1102 if (followfork) {
1103 praddset (&syscalls, SYS_fork);
1104#ifdef SYS_forkall
1105 praddset (&syscalls, SYS_forkall);
1106#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001107#ifdef SYS_fork1
John Hughes19e49982001-10-19 08:59:12 +00001108 praddset (&syscalls, SYS_fork1);
1109#endif
1110#ifdef SYS_rfork1
1111 praddset (&syscalls, SYS_rfork1);
1112#endif
1113#ifdef SYS_rforkall
1114 praddset (&syscalls, SYS_rforkall);
1115#endif
1116 }
1117 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 perror("PIOCSENTRY");
1119 return -1;
1120 }
John Hughes19e49982001-10-19 08:59:12 +00001121 /* Enable the syscall exits. */
1122 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 perror("PIOSEXIT");
1124 return -1;
1125 }
John Hughes19e49982001-10-19 08:59:12 +00001126 /* Enable signals we care about. */
1127 premptyset(&signals);
1128 for (i = 1; i < MAX_QUALS; ++i) {
1129 if (i > (sizeof signals) * CHAR_BIT) break;
1130 if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
1131 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001132 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 perror("PIOCSTRACE");
1134 return -1;
1135 }
John Hughes19e49982001-10-19 08:59:12 +00001136 /* Enable faults we care about */
1137 premptyset(&faults);
1138 for (i = 1; i < MAX_QUALS; ++i) {
1139 if (i > (sizeof faults) * CHAR_BIT) break;
1140 if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
1141 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001142 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 perror("PIOCSFAULT");
1144 return -1;
1145 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001146#else /* FREEBSD */
1147 /* set events flags. */
1148 arg = S_SIG | S_SCE | S_SCX ;
1149 if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1150 perror("PIOCBIS");
1151 return -1;
1152 }
1153#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 if (!attaching) {
1155#ifdef MIPS
1156 /*
1157 * The SGI PRSABORT doesn't work for pause() so
1158 * we send it a caught signal to wake it up.
1159 */
1160 kill(tcp->pid, SIGINT);
1161#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001162#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001164 arg = PRSABORT;
1165 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 perror("PIOCRUN");
1167 return -1;
1168 }
Roland McGrath553a6092002-12-16 20:40:39 +00001169#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001170#endif /* !MIPS*/
1171#ifdef FREEBSD
1172 /* wake up the child if it received the SIGSTOP */
1173 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001174#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 for (;;) {
1176 /* Wait for the child to do something. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001177 if (IOCTL_WSTOP (tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 perror("PIOCWSTOP");
1179 return -1;
1180 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001181 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001182 tcp->flags &= ~TCB_INSYSCALL;
1183 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001184 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 break;
1186 }
1187 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001188#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001189 arg = 0;
1190 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001191#else /* FREEBSD */
1192 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001193#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194 perror("PIOCRUN");
1195 return -1;
1196 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001197#ifdef FREEBSD
1198 /* handle the case where we "opened" the child before
1199 it did the kill -STOP */
1200 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1201 tcp->status.PR_WHAT == SIGSTOP)
1202 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001203#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001205#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001207#else /* FREEBSD */
1208 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001209 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001210 /* We are attaching to an already running process.
1211 * Try to figure out the state of the process in syscalls,
1212 * to handle the first event well.
1213 * This is done by having a look at the "wchan" property of the
1214 * process, which tells where it is stopped (if it is). */
1215 FILE * status;
1216 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001217
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001218 sprintf(proc, "/proc/%d/status", tcp->pid);
1219 status = fopen(proc, "r");
1220 if (status &&
1221 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1222 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1223 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1224 strcmp(wchan, "stopevent")) {
1225 /* The process is asleep in the middle of a syscall.
1226 Fake the syscall entry event */
1227 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1228 tcp->status.PR_WHY = PR_SYSENTRY;
1229 trace_syscall(tcp);
1230 }
1231 if (status)
1232 fclose(status);
1233 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001234 }
1235#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236#ifndef HAVE_POLLABLE_PROCFS
1237 if (proc_poll_pipe[0] != -1)
1238 proc_poller(tcp->pfd);
1239 else if (nprocs > 1) {
1240 proc_poll_open();
1241 proc_poller(last_pfd);
1242 proc_poller(tcp->pfd);
1243 }
1244 last_pfd = tcp->pfd;
1245#endif /* !HAVE_POLLABLE_PROCFS */
1246 return 0;
1247}
1248
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001249#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001251struct tcb *
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252pid2tcb(pid)
1253int pid;
1254{
1255 int i;
1256 struct tcb *tcp;
1257
Roland McGrathee9d4352002-12-18 04:16:10 +00001258 for (i = 0; i < tcbtabsize; i++) {
1259 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 if (pid && tcp->pid != pid)
1261 continue;
1262 if (tcp->flags & TCB_INUSE)
1263 return tcp;
1264 }
1265 return NULL;
1266}
1267
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001268#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269
1270static struct tcb *
1271pfd2tcb(pfd)
1272int pfd;
1273{
1274 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001275
Roland McGrathca16be82003-01-10 19:55:28 +00001276 for (i = 0; i < tcbtabsize; i++) {
1277 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001278 if (tcp->pfd != pfd)
1279 continue;
1280 if (tcp->flags & TCB_INUSE)
1281 return tcp;
1282 }
1283 return NULL;
1284}
1285
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001286#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287
1288void
1289droptcb(tcp)
1290struct tcb *tcp;
1291{
1292 if (tcp->pid == 0)
1293 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001294#ifdef TCB_CLONE_THREAD
1295 if (tcp->nclone_threads > 0) {
1296 /* There are other threads left in this process, but this
1297 is the one whose PID represents the whole process.
1298 We need to keep this record around as a zombie until
1299 all the threads die. */
1300 tcp->flags |= TCB_EXITING;
1301 return;
1302 }
1303#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 nprocs--;
1305 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001306
Roland McGrathe29341c2003-01-10 20:14:20 +00001307 if (tcp->parent != NULL) {
1308 tcp->parent->nchildren--;
1309#ifdef TCB_CLONE_THREAD
1310 if (tcp->flags & TCB_CLONE_DETACHED)
1311 tcp->parent->nclone_detached--;
1312 if (tcp->flags & TCB_CLONE_THREAD)
1313 tcp->parent->nclone_threads--;
1314#endif
Roland McGrath09623452003-05-23 02:27:13 +00001315#ifdef TCB_CLONE_DETACHED
1316 if (!(tcp->flags & TCB_CLONE_DETACHED))
1317#endif
1318 tcp->parent->nzombies++;
Roland McGrath276ceb32007-11-13 08:12:12 +00001319#ifdef LINUX
1320 /* Update `tcp->parent->parent->nchildren' and the other fields
1321 like NCLONE_DETACHED, only for zombie group leader that has
1322 already reported and been short-circuited at the top of this
1323 function. The same condition as at the top of DETACH. */
1324 if ((tcp->flags & TCB_CLONE_THREAD) &&
1325 tcp->parent->nclone_threads == 0 &&
1326 (tcp->parent->flags & TCB_EXITING))
1327 droptcb(tcp->parent);
1328#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001329 tcp->parent = NULL;
1330 }
1331
1332 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333 if (tcp->pfd != -1) {
1334 close(tcp->pfd);
1335 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001336#ifdef FREEBSD
1337 if (tcp->pfd_reg != -1) {
1338 close(tcp->pfd_reg);
1339 tcp->pfd_reg = -1;
1340 }
1341 if (tcp->pfd_status != -1) {
1342 close(tcp->pfd_status);
1343 tcp->pfd_status = -1;
1344 }
Roland McGrath553a6092002-12-16 20:40:39 +00001345#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001346#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001347 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001348#endif
1349 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001350
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001351 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001352 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001353
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354 tcp->outf = 0;
1355}
1356
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001357#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358
1359static int
1360resume(tcp)
1361struct tcb *tcp;
1362{
1363 if (tcp == NULL)
1364 return -1;
1365
1366 if (!(tcp->flags & TCB_SUSPENDED)) {
1367 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
1368 return -1;
1369 }
1370 tcp->flags &= ~TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001371#ifdef TCB_CLONE_THREAD
1372 if (tcp->flags & TCB_CLONE_THREAD)
1373 tcp->parent->nclone_waiting--;
1374#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001376 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378
1379 if (!qflag)
1380 fprintf(stderr, "Process %u resumed\n", tcp->pid);
1381 return 0;
1382}
1383
Roland McGrath1bfd3102007-08-03 10:02:00 +00001384static int
1385resume_from_tcp (struct tcb *tcp)
1386{
1387 int error = 0;
1388 int resumed = 0;
1389
1390 /* XXX This won't always be quite right (but it never was).
1391 A waiter with argument 0 or < -1 is waiting for any pid in
1392 a particular pgrp, which this child might or might not be
1393 in. The waiter will only wake up if it's argument is -1
1394 or if it's waiting for tcp->pid's pgrp. It makes a
1395 difference to wake up a waiter when there might be more
1396 traced children, because it could get a false ECHILD
1397 error. OTOH, if this was the last child in the pgrp, then
1398 it ought to wake up and get ECHILD. We would have to
1399 search the system for all pid's in the pgrp to be sure.
1400
1401 && (t->waitpid == -1 ||
1402 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1403 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1404 */
1405
1406 if (tcp->parent &&
1407 (tcp->parent->flags & TCB_SUSPENDED) &&
1408 (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1409 error = resume(tcp->parent);
1410 ++resumed;
1411 }
1412#ifdef TCB_CLONE_THREAD
1413 if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1414 /* Some other threads of our parent are waiting too. */
1415 unsigned int i;
1416
1417 /* Resume all the threads that were waiting for this PID. */
1418 for (i = 0; i < tcbtabsize; i++) {
1419 struct tcb *t = tcbtab[i];
1420 if (t->parent == tcp->parent && t != tcp
1421 && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1422 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1423 && t->waitpid == tcp->pid) {
1424 error |= resume (t);
1425 ++resumed;
1426 }
1427 }
1428 if (resumed == 0)
1429 /* Noone was waiting for this PID in particular,
1430 so now we might need to resume some wildcarders. */
1431 for (i = 0; i < tcbtabsize; i++) {
1432 struct tcb *t = tcbtab[i];
1433 if (t->parent == tcp->parent && t != tcp
1434 && ((t->flags
1435 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1436 == (TCB_CLONE_THREAD|TCB_SUSPENDED))
1437 && t->waitpid <= 0
1438 ) {
1439 error |= resume (t);
1440 break;
1441 }
1442 }
1443 }
1444
1445 return error;
1446}
1447#endif
1448
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001449#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450
Roland McGrath0a463882007-07-05 18:43:16 +00001451/* detach traced process; continue with sig
1452 Never call DETACH twice on the same process as both unattached and
1453 attached-unstopped processes give the same ESRCH. For unattached process we
1454 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455
1456static int
1457detach(tcp, sig)
1458struct tcb *tcp;
1459int sig;
1460{
1461 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001462#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001463 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001464 struct tcb *zombie = NULL;
1465
1466 /* If the group leader is lingering only because of this other
1467 thread now dying, then detach the leader as well. */
1468 if ((tcp->flags & TCB_CLONE_THREAD) &&
1469 tcp->parent->nclone_threads == 1 &&
1470 (tcp->parent->flags & TCB_EXITING))
1471 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001472#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473
1474 if (tcp->flags & TCB_BPTSET)
1475 sig = SIGKILL;
1476
1477#ifdef LINUX
1478 /*
1479 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001480 * before detaching. Arghh. We go through hoops
1481 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001483#if defined(SPARC)
1484#undef PTRACE_DETACH
1485#define PTRACE_DETACH PTRACE_SUNDETACH
1486#endif
Roland McGrath02203312007-06-11 22:06:31 +00001487 /*
1488 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1489 * expected SIGSTOP. We must catch exactly one as otherwise the
1490 * detached process would be left stopped (process state T).
1491 */
1492 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1494 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001495 }
1496 else if (errno != ESRCH) {
1497 /* Shouldn't happen. */
1498 perror("detach: ptrace(PTRACE_DETACH, ...)");
1499 }
Roland McGrath134813a2007-06-02 00:07:33 +00001500 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1501 : tcp->pid),
1502 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001503 if (errno != ESRCH)
1504 perror("detach: checking sanity");
1505 }
Roland McGrath02203312007-06-11 22:06:31 +00001506 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1507 ? tcp->parent->pid : tcp->pid),
1508 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001509 if (errno != ESRCH)
1510 perror("detach: stopping child");
1511 }
Roland McGrath02203312007-06-11 22:06:31 +00001512 else
1513 catch_sigstop = 1;
1514 if (catch_sigstop)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001516#ifdef __WALL
1517 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1518 if (errno == ECHILD) /* Already gone. */
1519 break;
1520 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001521 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001522 break;
1523 }
1524#endif /* __WALL */
1525 /* No __WALL here. */
1526 if (waitpid(tcp->pid, &status, 0) < 0) {
1527 if (errno != ECHILD) {
1528 perror("detach: waiting");
1529 break;
1530 }
1531#ifdef __WCLONE
1532 /* If no processes, try clones. */
1533 if (wait4(tcp->pid, &status, __WCLONE,
1534 NULL) < 0) {
1535 if (errno != ECHILD)
1536 perror("detach: waiting");
1537 break;
1538 }
1539#endif /* __WCLONE */
1540 }
1541#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001542 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001543#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 if (!WIFSTOPPED(status)) {
1545 /* Au revoir, mon ami. */
1546 break;
1547 }
1548 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001549 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550 break;
1551 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001552 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00001553 WSTOPSIG(status) == tcp->sigtrap80 ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001554 : WSTOPSIG(status));
1555 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001558#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559
1560#if defined(SUNOS4)
1561 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1562 if (sig && kill(tcp->pid, sig) < 0)
1563 perror("detach: kill");
1564 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001565 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566#endif /* SUNOS4 */
1567
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001568#ifndef USE_PROCFS
Roland McGrath1bfd3102007-08-03 10:02:00 +00001569 error |= resume_from_tcp (tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001570#endif
1571
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 if (!qflag)
1573 fprintf(stderr, "Process %u detached\n", tcp->pid);
1574
1575 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001576
1577#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001578 if (zombie != NULL) {
1579 /* TCP no longer exists therefore you must not detach () it. */
1580 droptcb(zombie);
1581 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001582#endif
1583
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584 return error;
1585}
1586
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001587#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588
1589static void
1590reaper(sig)
1591int sig;
1592{
1593 int pid;
1594 int status;
1595
1596 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1597#if 0
1598 struct tcb *tcp;
1599
1600 tcp = pid2tcb(pid);
1601 if (tcp)
1602 droptcb(tcp);
1603#endif
1604 }
1605}
1606
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001607#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608
1609static void
1610cleanup()
1611{
1612 int i;
1613 struct tcb *tcp;
1614
Roland McGrathee9d4352002-12-18 04:16:10 +00001615 for (i = 0; i < tcbtabsize; i++) {
1616 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617 if (!(tcp->flags & TCB_INUSE))
1618 continue;
1619 if (debug)
1620 fprintf(stderr,
1621 "cleanup: looking at pid %u\n", tcp->pid);
1622 if (tcp_last &&
1623 (!outfname || followfork < 2 || tcp_last == tcp)) {
1624 tprintf(" <unfinished ...>\n");
1625 tcp_last = NULL;
1626 }
1627 if (tcp->flags & TCB_ATTACHED)
1628 detach(tcp, 0);
1629 else {
1630 kill(tcp->pid, SIGCONT);
1631 kill(tcp->pid, SIGTERM);
1632 }
1633 }
1634 if (cflag)
1635 call_summary(outf);
1636}
1637
1638static void
1639interrupt(sig)
1640int sig;
1641{
1642 interrupted = 1;
1643}
1644
1645#ifndef HAVE_STRERROR
1646
Roland McGrath6d2b3492002-12-30 00:51:30 +00001647#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648extern int sys_nerr;
1649extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001650#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651
1652const char *
1653strerror(errno)
1654int errno;
1655{
1656 static char buf[64];
1657
1658 if (errno < 1 || errno >= sys_nerr) {
1659 sprintf(buf, "Unknown error %d", errno);
1660 return buf;
1661 }
1662 return sys_errlist[errno];
1663}
1664
1665#endif /* HAVE_STERRROR */
1666
1667#ifndef HAVE_STRSIGNAL
1668
Roland McGrath8f474e02003-01-14 07:53:33 +00001669#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001670extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001672#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1673extern char *_sys_siglist[];
1674#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675
1676const char *
1677strsignal(sig)
1678int sig;
1679{
1680 static char buf[64];
1681
1682 if (sig < 1 || sig >= NSIG) {
1683 sprintf(buf, "Unknown signal %d", sig);
1684 return buf;
1685 }
1686#ifdef HAVE__SYS_SIGLIST
1687 return _sys_siglist[sig];
1688#else
1689 return sys_siglist[sig];
1690#endif
1691}
1692
1693#endif /* HAVE_STRSIGNAL */
1694
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001695#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696
1697static void
1698rebuild_pollv()
1699{
1700 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701
Roland McGrathee9d4352002-12-18 04:16:10 +00001702 if (pollv != NULL)
1703 free (pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001704 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001705 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001706 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001707 exit(1);
1708 }
1709
Roland McGrathca16be82003-01-10 19:55:28 +00001710 for (i = j = 0; i < tcbtabsize; i++) {
1711 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 if (!(tcp->flags & TCB_INUSE))
1713 continue;
1714 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001715 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716 j++;
1717 }
1718 if (j != nprocs) {
1719 fprintf(stderr, "strace: proc miscount\n");
1720 exit(1);
1721 }
1722}
1723
1724#ifndef HAVE_POLLABLE_PROCFS
1725
1726static void
1727proc_poll_open()
1728{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729 int i;
1730
1731 if (pipe(proc_poll_pipe) < 0) {
1732 perror("pipe");
1733 exit(1);
1734 }
1735 for (i = 0; i < 2; i++) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001736 if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737 exit(1);
1738 }
1739 }
1740}
1741
1742static int
1743proc_poll(pollv, nfds, timeout)
1744struct pollfd *pollv;
1745int nfds;
1746int timeout;
1747{
1748 int i;
1749 int n;
1750 struct proc_pollfd pollinfo;
1751
1752 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1753 return n;
1754 if (n != sizeof(struct proc_pollfd)) {
1755 fprintf(stderr, "panic: short read: %d\n", n);
1756 exit(1);
1757 }
1758 for (i = 0; i < nprocs; i++) {
1759 if (pollv[i].fd == pollinfo.fd)
1760 pollv[i].revents = pollinfo.revents;
1761 else
1762 pollv[i].revents = 0;
1763 }
1764 poller_pid = pollinfo.pid;
1765 return 1;
1766}
1767
1768static void
1769wakeup_handler(sig)
1770int sig;
1771{
1772}
1773
1774static void
1775proc_poller(pfd)
1776int pfd;
1777{
1778 struct proc_pollfd pollinfo;
1779 struct sigaction sa;
1780 sigset_t blocked_set, empty_set;
1781 int i;
1782 int n;
1783 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001784#ifdef FREEBSD
1785 struct procfs_status pfs;
1786#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787
1788 switch (fork()) {
1789 case -1:
1790 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001791 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 case 0:
1793 break;
1794 default:
1795 return;
1796 }
1797
1798 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1799 sa.sa_flags = 0;
1800 sigemptyset(&sa.sa_mask);
1801 sigaction(SIGHUP, &sa, NULL);
1802 sigaction(SIGINT, &sa, NULL);
1803 sigaction(SIGQUIT, &sa, NULL);
1804 sigaction(SIGPIPE, &sa, NULL);
1805 sigaction(SIGTERM, &sa, NULL);
1806 sa.sa_handler = wakeup_handler;
1807 sigaction(SIGUSR1, &sa, NULL);
1808 sigemptyset(&blocked_set);
1809 sigaddset(&blocked_set, SIGUSR1);
1810 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1811 sigemptyset(&empty_set);
1812
1813 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1814 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001815 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816 }
1817 n = rl.rlim_cur;
1818 for (i = 0; i < n; i++) {
1819 if (i != pfd && i != proc_poll_pipe[1])
1820 close(i);
1821 }
1822
1823 pollinfo.fd = pfd;
1824 pollinfo.pid = getpid();
1825 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001826#ifndef FREEBSD
1827 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1828#else /* FREEBSD */
1829 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1830#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001831 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832 switch (errno) {
1833 case EINTR:
1834 continue;
1835 case EBADF:
1836 pollinfo.revents = POLLERR;
1837 break;
1838 case ENOENT:
1839 pollinfo.revents = POLLHUP;
1840 break;
1841 default:
1842 perror("proc_poller: PIOCWSTOP");
1843 }
1844 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1845 _exit(0);
1846 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001847 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1849 sigsuspend(&empty_set);
1850 }
1851}
1852
1853#endif /* !HAVE_POLLABLE_PROCFS */
1854
1855static int
1856choose_pfd()
1857{
1858 int i, j;
1859 struct tcb *tcp;
1860
1861 static int last;
1862
1863 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001864 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 /*
1866 * The previous process is ready to run again. We'll
1867 * let it do so if it is currently in a syscall. This
1868 * heuristic improves the readability of the trace.
1869 */
1870 tcp = pfd2tcb(pollv[last].fd);
1871 if (tcp && (tcp->flags & TCB_INSYSCALL))
1872 return pollv[last].fd;
1873 }
1874
1875 for (i = 0; i < nprocs; i++) {
1876 /* Let competing children run round robin. */
1877 j = (i + last + 1) % nprocs;
1878 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1879 tcp = pfd2tcb(pollv[j].fd);
1880 if (!tcp) {
1881 fprintf(stderr, "strace: lost proc\n");
1882 exit(1);
1883 }
1884 droptcb(tcp);
1885 return -1;
1886 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001887 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001888 last = j;
1889 return pollv[j].fd;
1890 }
1891 }
1892 fprintf(stderr, "strace: nothing ready\n");
1893 exit(1);
1894}
1895
1896static int
1897trace()
1898{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001899#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001900 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001901#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 struct tcb *tcp;
1903 int pfd;
1904 int what;
1905 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001906 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907
1908 for (;;) {
1909 if (interactive)
1910 sigprocmask(SIG_SETMASK, &empty_set, NULL);
1911
1912 if (nprocs == 0)
1913 break;
1914
1915 switch (nprocs) {
1916 case 1:
1917#ifndef HAVE_POLLABLE_PROCFS
1918 if (proc_poll_pipe[0] == -1) {
1919#endif
1920 tcp = pid2tcb(0);
1921 if (!tcp)
1922 continue;
1923 pfd = tcp->pfd;
1924 if (pfd == -1)
1925 continue;
1926 break;
1927#ifndef HAVE_POLLABLE_PROCFS
1928 }
1929 /* fall through ... */
1930#endif /* !HAVE_POLLABLE_PROCFS */
1931 default:
1932#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001933#ifdef POLL_HACK
1934 /* On some systems (e.g. UnixWare) we get too much ugly
1935 "unfinished..." stuff when multiple proceses are in
1936 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00001937
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001938 if (in_syscall) {
1939 struct pollfd pv;
1940 tcp = in_syscall;
1941 in_syscall = NULL;
1942 pv.fd = tcp->pfd;
1943 pv.events = POLLWANT;
1944 if ((what = poll (&pv, 1, 1)) < 0) {
1945 if (interrupted)
1946 return 0;
1947 continue;
1948 }
1949 else if (what == 1 && pv.revents & POLLWANT) {
1950 goto FOUND;
1951 }
1952 }
1953#endif
1954
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 if (poll(pollv, nprocs, INFTIM) < 0) {
1956 if (interrupted)
1957 return 0;
1958 continue;
1959 }
1960#else /* !HAVE_POLLABLE_PROCFS */
1961 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1962 if (interrupted)
1963 return 0;
1964 continue;
1965 }
1966#endif /* !HAVE_POLLABLE_PROCFS */
1967 pfd = choose_pfd();
1968 if (pfd == -1)
1969 continue;
1970 break;
1971 }
1972
1973 /* Look up `pfd' in our table. */
1974 if ((tcp = pfd2tcb(pfd)) == NULL) {
1975 fprintf(stderr, "unknown pfd: %u\n", pfd);
1976 exit(1);
1977 }
John Hughesb6643082002-05-23 11:02:22 +00001978#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001979 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00001980#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981 /* Get the status of the process. */
1982 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001983#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001984 ioctl_result = IOCTL_WSTOP (tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001985#else /* FREEBSD */
1986 /* Thanks to some scheduling mystery, the first poller
1987 sometimes waits for the already processed end of fork
1988 event. Doing a non blocking poll here solves the problem. */
1989 if (proc_poll_pipe[0] != -1)
1990 ioctl_result = IOCTL_STATUS (tcp);
1991 else
1992 ioctl_result = IOCTL_WSTOP (tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00001993#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001994 ioctl_errno = errno;
1995#ifndef HAVE_POLLABLE_PROCFS
1996 if (proc_poll_pipe[0] != -1) {
1997 if (ioctl_result < 0)
1998 kill(poller_pid, SIGKILL);
1999 else
2000 kill(poller_pid, SIGUSR1);
2001 }
2002#endif /* !HAVE_POLLABLE_PROCFS */
2003 }
2004 if (interrupted)
2005 return 0;
2006
2007 if (interactive)
2008 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2009
2010 if (ioctl_result < 0) {
2011 /* Find out what happened if it failed. */
2012 switch (ioctl_errno) {
2013 case EINTR:
2014 case EBADF:
2015 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002016#ifdef FREEBSD
2017 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002018#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019 case ENOENT:
2020 droptcb(tcp);
2021 continue;
2022 default:
2023 perror("PIOCWSTOP");
2024 exit(1);
2025 }
2026 }
2027
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002028#ifdef FREEBSD
2029 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2030 /* discard first event for a syscall we never entered */
2031 IOCTL (tcp->pfd, PIOCRUN, 0);
2032 continue;
2033 }
Roland McGrath553a6092002-12-16 20:40:39 +00002034#endif
2035
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002036 /* clear the just started flag */
2037 tcp->flags &= ~TCB_STARTUP;
2038
2039 /* set current output file */
2040 outf = tcp->outf;
2041
2042 if (cflag) {
2043 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002044#ifdef FREEBSD
2045 char buf[1024];
2046 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002048 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2049 buf[len] = '\0';
2050 sscanf(buf,
2051 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2052 &stime.tv_sec, &stime.tv_usec);
2053 } else
2054 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002055#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2057 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002058#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2060 tcp->stime = stime;
2061 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002062 what = tcp->status.PR_WHAT;
2063 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002064#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002066 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2067 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068 if (trace_syscall(tcp) < 0) {
2069 fprintf(stderr, "syscall trouble\n");
2070 exit(1);
2071 }
2072 }
2073 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002074#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002075 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002076#ifdef POLL_HACK
2077 in_syscall = tcp;
2078#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 case PR_SYSEXIT:
2080 if (trace_syscall(tcp) < 0) {
2081 fprintf(stderr, "syscall trouble\n");
2082 exit(1);
2083 }
2084 break;
2085 case PR_SIGNALLED:
2086 if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
2087 printleader(tcp);
2088 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002089 signame(what), strsignal(what));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 printtrailer(tcp);
John Hughes58265892001-10-18 15:13:53 +00002091#ifdef PR_INFO
2092 if (tcp->status.PR_INFO.si_signo == what) {
2093 printleader(tcp);
2094 tprintf(" siginfo=");
2095 printsiginfo(&tcp->status.PR_INFO, 1);
2096 printtrailer(tcp);
2097 }
2098#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 }
2100 break;
2101 case PR_FAULTED:
2102 if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
2103 printleader(tcp);
2104 tprintf("=== FAULT %d ===", what);
2105 printtrailer(tcp);
2106 }
2107 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002108#ifdef FREEBSD
2109 case 0: /* handle case we polled for nothing */
2110 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002111#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002113 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 exit(1);
2115 break;
2116 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002117 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002118#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002119 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002120#else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002121 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00002122#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123 perror("PIOCRUN");
2124 exit(1);
2125 }
2126 }
2127 return 0;
2128}
2129
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002130#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002131
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002132#ifdef TCB_GROUP_EXITING
2133/* Handle an exit detach or death signal that is taking all the
2134 related clone threads with it. This is called in three circumstances:
2135 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2136 SIG == 0 Continuing TCP will perform an exit_group syscall.
2137 SIG == other Continuing TCP with SIG will kill the process.
2138*/
2139static int
2140handle_group_exit(struct tcb *tcp, int sig)
2141{
2142 /* We need to locate our records of all the clone threads
2143 related to TCP, either its children or siblings. */
2144 struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2145 ? tcp->parent
2146 : tcp->nclone_detached > 0
2147 ? tcp : NULL);
2148
2149 if (sig < 0) {
Roland McGrath05690952004-10-20 01:00:27 +00002150 if (leader != NULL && leader != tcp &&
2151 !(leader->flags & TCB_GROUP_EXITING))
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002152 fprintf(stderr,
2153 "PANIC: handle_group_exit: %d leader %d\n",
2154 tcp->pid, leader ? leader->pid : -1);
Roland McGrath0a463882007-07-05 18:43:16 +00002155 /* TCP no longer exists therefore you must not detach () it. */
Roland McGrath1bfd3102007-08-03 10:02:00 +00002156#ifndef USE_PROCFS
2157 resume_from_tcp (tcp);
2158#endif
Roland McGrath0a463882007-07-05 18:43:16 +00002159 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002160 }
2161 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002162 /* Mark that we are taking the process down. */
2163 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002164 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002165 detach(tcp, sig);
Roland McGrath1bfd3102007-08-03 10:02:00 +00002166 if (leader != NULL && leader != tcp)
2167 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002168 } else {
2169 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2170 cleanup();
2171 return -1;
2172 }
2173 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002174 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002175 if (leader != tcp)
2176 droptcb(tcp);
2177 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002178 /* The leader will report to us as parent now,
2179 and then we'll get to the SIG==-1 case. */
2180 return 0;
2181 }
2182 }
2183
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002184 return 0;
2185}
2186#endif
2187
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188static int
2189trace()
2190{
2191 int pid;
2192 int wait_errno;
2193 int status;
2194 struct tcb *tcp;
2195#ifdef LINUX
2196 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002197#ifdef __WALL
2198 static int wait4_options = __WALL;
2199#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200#endif /* LINUX */
2201
2202 while (nprocs != 0) {
Roland McGrath02203312007-06-11 22:06:31 +00002203 if (interrupted)
2204 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002205 if (interactive)
2206 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2207#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002208#ifdef __WALL
2209 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002210 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002211 /* this kernel does not support __WALL */
2212 wait4_options &= ~__WALL;
2213 errno = 0;
2214 pid = wait4(-1, &status, wait4_options,
2215 cflag ? &ru : NULL);
2216 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002217 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002218 /* most likely a "cloned" process */
2219 pid = wait4(-1, &status, __WCLONE,
2220 cflag ? &ru : NULL);
2221 if (pid == -1) {
2222 fprintf(stderr, "strace: clone wait4 "
2223 "failed: %s\n", strerror(errno));
2224 }
2225 }
2226#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002228#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229#endif /* LINUX */
2230#ifdef SUNOS4
2231 pid = wait(&status);
2232#endif /* SUNOS4 */
2233 wait_errno = errno;
2234 if (interactive)
2235 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2236
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237 if (pid == -1) {
2238 switch (wait_errno) {
2239 case EINTR:
2240 continue;
2241 case ECHILD:
2242 /*
2243 * We would like to verify this case
2244 * but sometimes a race in Solbourne's
2245 * version of SunOS sometimes reports
2246 * ECHILD before sending us SIGCHILD.
2247 */
2248#if 0
2249 if (nprocs == 0)
2250 return 0;
2251 fprintf(stderr, "strace: proc miscount\n");
2252 exit(1);
2253#endif
2254 return 0;
2255 default:
2256 errno = wait_errno;
2257 perror("strace: wait");
2258 return -1;
2259 }
2260 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002261 if (pid == popen_pid) {
2262 if (WIFEXITED(status) || WIFSIGNALED(status))
2263 popen_pid = -1;
2264 continue;
2265 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 if (debug)
2267 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2268
2269 /* Look up `pid' in our table. */
2270 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002271#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002272 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002273 /* This is needed to go with the CLONE_PTRACE
2274 changes in process.c/util.c: we might see
2275 the child's initial trap before we see the
2276 parent return from the clone syscall.
2277 Leave the child suspended until the parent
2278 returns from its system call. Only then
2279 will we have the association of parent and
2280 child so that we know how to do clearbpt
2281 in the child. */
Dmitry V. Levin76860f62006-10-11 22:55:25 +00002282 if (nprocs == tcbtabsize &&
2283 expand_tcbtab())
2284 tcp = NULL;
2285 else
2286 tcp = alloctcb(pid);
2287 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002288 kill(pid, SIGKILL); /* XXX */
2289 return 0;
2290 }
2291 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002292 if (!qflag)
2293 fprintf(stderr, "\
2294Process %d attached (waiting for parent)\n",
2295 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002296 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002297 else
2298 /* This can happen if a clone call used
2299 CLONE_PTRACE itself. */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002300#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002301 {
2302 fprintf(stderr, "unknown pid: %u\n", pid);
2303 if (WIFSTOPPED(status))
2304 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2305 exit(1);
2306 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002307 }
2308 /* set current output file */
2309 outf = tcp->outf;
2310 if (cflag) {
2311#ifdef LINUX
2312 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2313 tcp->stime = ru.ru_stime;
2314#endif /* !LINUX */
2315 }
2316
2317 if (tcp->flags & TCB_SUSPENDED) {
2318 /*
2319 * Apparently, doing any ptrace() call on a stopped
2320 * process, provokes the kernel to report the process
2321 * status again on a subsequent wait(), even if the
2322 * process has not been actually restarted.
2323 * Since we have inspected the arguments of suspended
2324 * processes we end up here testing for this case.
2325 */
2326 continue;
2327 }
2328 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002329 if (pid == strace_child)
2330 exit_code = 0x100 | WTERMSIG(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002331 if (!cflag
2332 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2333 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002334 tprintf("+++ killed by %s %s+++",
2335 signame(WTERMSIG(status)),
2336#ifdef WCOREDUMP
2337 WCOREDUMP(status) ? "(core dumped) " :
2338#endif
2339 "");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340 printtrailer(tcp);
2341 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002342#ifdef TCB_GROUP_EXITING
2343 handle_group_exit(tcp, -1);
2344#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002346#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 continue;
2348 }
2349 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002350 if (pid == strace_child)
2351 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352 if (debug)
2353 fprintf(stderr, "pid %u exited\n", pid);
Roland McGrath05690952004-10-20 01:00:27 +00002354 if ((tcp->flags & TCB_ATTACHED)
2355#ifdef TCB_GROUP_EXITING
2356 && !(tcp->parent && (tcp->parent->flags &
2357 TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002358 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002359#endif
2360 )
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002361 fprintf(stderr,
2362 "PANIC: attached pid %u exited\n",
2363 pid);
Roland McGrath0a396902003-06-10 03:05:53 +00002364 if (tcp == tcp_last) {
2365 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
2366 == TCB_INSYSCALL)
2367 tprintf(" <unfinished ... exit status %d>\n",
2368 WEXITSTATUS(status));
2369 tcp_last = NULL;
2370 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002371#ifdef TCB_GROUP_EXITING
2372 handle_group_exit(tcp, -1);
2373#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002375#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 continue;
2377 }
2378 if (!WIFSTOPPED(status)) {
2379 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2380 droptcb(tcp);
2381 continue;
2382 }
2383 if (debug)
2384 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002385 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386
Roland McGrath02203312007-06-11 22:06:31 +00002387 /*
2388 * Interestingly, the process may stop
2389 * with STOPSIG equal to some other signal
2390 * than SIGSTOP if we happend to attach
2391 * just before the process takes a signal.
2392 */
2393 if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 /*
2395 * This flag is there to keep us in sync.
2396 * Next time this process stops it should
2397 * really be entering a system call.
2398 */
2399 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002400 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002401 /*
2402 * One example is a breakpoint inherited from
2403 * parent through fork ().
2404 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002405 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2406 droptcb(tcp);
2407 cleanup();
2408 return -1;
2409 }
2410 }
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002411#ifdef LINUX /* add more OSes after you verified it works for them */
2412 /*
2413 * Ask kernel to set signo to SIGTRAP | 0x80
2414 * on ptrace-generated SIGTRAPs, and mark
2415 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
2416 */
2417 if (tcp->sigtrap80 == SIGTRAP
2418 && ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
2419 (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0) {
2420 tcp->sigtrap80 = SIGTRAP | 0x80;
2421 }
2422#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002423 goto tracing;
2424 }
2425
Denys Vlasenko1e3ce322008-12-22 19:14:47 +00002426#ifdef LINUX
2427 if (tcp->sigtrap80 != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
2428 /*
2429 * We told ptrace to report SIGTRAP | 0x80 on this process
2430 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
2431 * kill(pid, SIGTRAP), trap insn, etc;
2432 * but be paranoid about it.
2433 */
2434 if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
2435 /* It's post-exec ptrace stop. */
2436 /* Set WSTOPSIG(status) = (SIGTRAP | 0x80). */
2437 status |= 0x8000;
2438 } else {
2439 /* Take a better look... */
2440 siginfo_t si;
2441 ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
2442 /*
2443 * Check some fields to make sure we see
2444 * real SIGTRAP.
2445 * Otherwise interpret it as ptrace stop.
2446 * Real SIGTRAPs (int3 insn on x86, kill() etc)
2447 * have these values:
2448 * int3: kill -TRAP $pid:
2449 * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
2450 * si_errno:0 si_errno:(?)
2451 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
2452 * si_pid:0 si_pid:(>0?)
2453 * si_band:0 si_band:(?)
2454 * Ptrace stops have garbage there instead.
2455 */
2456 if (si.si_signo != SIGTRAP
2457 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
2458 ) {
2459 fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming it's ptrace stop\n", si.si_code);
2460 /* Set WSTOPSIG(status) = (SIGTRAP | 0x80). */
2461 status |= 0x8000;
2462 }
2463 }
2464 }
2465
2466 if (WSTOPSIG(status) == (SIGTRAP | 0x80)
2467 /* && tcp->sigtrap80 == SIGTRAP - redundant */
2468 ) {
2469 /*
2470 * If tcp->sigtrap80 == SIGTRAP but we got it
2471 * ORed with 0x80, it's a CLONE_PTRACEd child
2472 * which inherited "SIGTRAP | 0x80" setting.
2473 * Whee. Just record this remarkable fact.
2474 */
2475 tcp->sigtrap80 = (SIGTRAP | 0x80);
2476 }
2477#endif
2478
2479 if (WSTOPSIG(status) != tcp->sigtrap80) {
2480 /* This isn't a ptrace stop. */
2481
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002482 if (WSTOPSIG(status) == SIGSTOP &&
2483 (tcp->flags & TCB_SIGTRAPPED)) {
2484 /*
2485 * Trapped attempt to block SIGTRAP
2486 * Hope we are back in control now.
2487 */
2488 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002489 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002490 cleanup();
2491 return -1;
2492 }
2493 continue;
2494 }
2495 if (!cflag
2496 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002497 unsigned long addr = 0;
2498 long pc = 0;
Dmitry V. Levin96339422006-10-11 23:11:43 +00002499#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002500# define PSR_RI 41
2501 struct siginfo si;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002502 long psr;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002503
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002504 upeek(tcp, PT_CR_IPSR, &psr);
2505 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002506
2507 pc += (psr >> PSR_RI) & 0x3;
2508 ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
2509 addr = (unsigned long) si.si_addr;
Roland McGrath3a055d72005-03-06 22:24:29 +00002510#elif defined PTRACE_GETSIGINFO
2511 if (WSTOPSIG(status) == SIGSEGV ||
2512 WSTOPSIG(status) == SIGBUS) {
2513 siginfo_t si;
2514 if (ptrace(PTRACE_GETSIGINFO, pid,
2515 0, &si) == 0)
2516 addr = (unsigned long)
2517 si.si_addr;
2518 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002519#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002520 printleader(tcp);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002521 tprintf("--- %s (%s) @ %lx (%lx) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002522 signame(WSTOPSIG(status)),
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002523 strsignal(WSTOPSIG(status)), pc, addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002524 printtrailer(tcp);
2525 }
Roland McGrath05690952004-10-20 01:00:27 +00002526 if (((tcp->flags & TCB_ATTACHED) ||
2527 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002528 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002529#ifdef TCB_GROUP_EXITING
2530 handle_group_exit(tcp, WSTOPSIG(status));
2531#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002532 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002533#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 continue;
2535 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002536 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 cleanup();
2538 return -1;
2539 }
2540 tcp->flags &= ~TCB_SUSPENDED;
2541 continue;
2542 }
Roland McGrath02203312007-06-11 22:06:31 +00002543 /* we handled the STATUS, we are permitted to interrupt now. */
2544 if (interrupted)
2545 return 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002546 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002547 if (tcp->flags & TCB_ATTACHED)
2548 detach(tcp, 0);
2549 else {
2550 ptrace(PTRACE_KILL,
2551 tcp->pid, (char *) 1, SIGTERM);
2552 droptcb(tcp);
2553 }
2554 continue;
2555 }
2556 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002557#ifdef TCB_GROUP_EXITING
2558 if (tcp->flags & TCB_GROUP_EXITING) {
2559 if (handle_group_exit(tcp, 0) < 0)
2560 return -1;
2561 continue;
2562 }
2563#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002564 if (tcp->flags & TCB_ATTACHED)
2565 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002566 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002567 cleanup();
2568 return -1;
2569 }
2570 continue;
2571 }
2572 if (tcp->flags & TCB_SUSPENDED) {
2573 if (!qflag)
2574 fprintf(stderr, "Process %u suspended\n", pid);
2575 continue;
2576 }
2577 tracing:
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002578 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002579 cleanup();
2580 return -1;
2581 }
2582 }
2583 return 0;
2584}
2585
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002586#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002587
2588static int curcol;
2589
2590#ifdef __STDC__
2591#include <stdarg.h>
2592#define VA_START(a, b) va_start(a, b)
2593#else
2594#include <varargs.h>
2595#define VA_START(a, b) va_start(a)
2596#endif
2597
2598void
2599#ifdef __STDC__
2600tprintf(const char *fmt, ...)
2601#else
2602tprintf(fmt, va_alist)
2603char *fmt;
2604va_dcl
2605#endif
2606{
2607 va_list args;
2608
2609 VA_START(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002610 if (outf) {
2611 int n = vfprintf(outf, fmt, args);
2612 if (n < 0 && outf != stderr)
2613 perror(outfname == NULL
2614 ? "<writing to pipe>" : outfname);
2615 else
2616 curcol += n;
2617 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002618 va_end(args);
2619 return;
2620}
2621
2622void
2623printleader(tcp)
2624struct tcb *tcp;
2625{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002626 if (tcp_last) {
2627 if (tcp_last->ptrace_errno) {
2628 if (tcp_last->flags & TCB_INSYSCALL) {
2629 tprintf(" <unavailable>)");
2630 tabto(acolumn);
2631 }
2632 tprintf("= ? <unavailable>\n");
2633 tcp_last->ptrace_errno = 0;
2634 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
2635 tcp_last->flags |= TCB_REPRINT;
2636 tprintf(" <unfinished ...>\n");
2637 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002638 }
2639 curcol = 0;
2640 if ((followfork == 1 || pflag_seen > 1) && outfname)
2641 tprintf("%-5d ", tcp->pid);
2642 else if (nprocs > 1 && !outfname)
2643 tprintf("[pid %5u] ", tcp->pid);
2644 if (tflag) {
2645 char str[sizeof("HH:MM:SS")];
2646 struct timeval tv, dtv;
2647 static struct timeval otv;
2648
2649 gettimeofday(&tv, NULL);
2650 if (rflag) {
2651 if (otv.tv_sec == 0)
2652 otv = tv;
2653 tv_sub(&dtv, &tv, &otv);
2654 tprintf("%6ld.%06ld ",
2655 (long) dtv.tv_sec, (long) dtv.tv_usec);
2656 otv = tv;
2657 }
2658 else if (tflag > 2) {
2659 tprintf("%ld.%06ld ",
2660 (long) tv.tv_sec, (long) tv.tv_usec);
2661 }
2662 else {
2663 time_t local = tv.tv_sec;
2664 strftime(str, sizeof(str), "%T", localtime(&local));
2665 if (tflag > 1)
2666 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2667 else
2668 tprintf("%s ", str);
2669 }
2670 }
2671 if (iflag)
2672 printcall(tcp);
2673}
2674
2675void
2676tabto(col)
2677int col;
2678{
2679 if (curcol < col)
2680 tprintf("%*s", col - curcol, "");
2681}
2682
2683void
2684printtrailer(tcp)
2685struct tcb *tcp;
2686{
2687 tprintf("\n");
2688 tcp_last = NULL;
2689}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002690
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002691#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002692
2693int mp_ioctl (int fd, int cmd, void *arg, int size) {
2694
2695 struct iovec iov[2];
2696 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002697
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002698 iov[0].iov_base = &cmd;
2699 iov[0].iov_len = sizeof cmd;
2700 if (arg) {
2701 ++n;
2702 iov[1].iov_base = arg;
2703 iov[1].iov_len = size;
2704 }
Roland McGrath553a6092002-12-16 20:40:39 +00002705
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002706 return writev (fd, iov, n);
2707}
2708
2709#endif