134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project/*
234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * All rights reserved.
734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *
834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * Redistribution and use in source and binary forms, with or without
934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * modification, are permitted provided that the following conditions
1034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * are met:
1134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
1234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
1334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
1434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
1534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *    documentation and/or other materials provided with the distribution.
1634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * 3. The name of the author may not be used to endorse or promote products
1734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *    derived from this software without specific prior written permission.
1834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *
1934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project *
30f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown *	$Id$
3134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project */
3234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
3334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include "defs.h"
3434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
3534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/types.h>
3634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <signal.h>
3734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <errno.h>
3834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/param.h>
3934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <fcntl.h>
4034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/resource.h>
41f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef HAVE_ANDROID_OS
42f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#define wait4 __wait4
4334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/wait.h>
44f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
4534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/stat.h>
4634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <pwd.h>
4734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <grp.h>
4834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <string.h>
4934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <limits.h>
5034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <dirent.h>
5134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
52f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
53f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# include <asm/unistd.h>
54f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# if defined __NR_tgkill
55f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#  define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
56f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# elif defined __NR_tkill
57f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#  define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
58f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# else
59f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown   /* kill() may choose arbitrarily the target task of the process group
60f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown      while we later wait on a that specific TID.  PID process waits become
61f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown      TID task specific waits for a process under ptrace(2).  */
62f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
63f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#  define my_tgkill(pid, tid, sig) kill ((tid), (sig))
64f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# endif
65f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
66f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
6734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#if defined(IA64) && defined(LINUX)
6834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project# include <asm/ptrace_offsets.h>
6934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
7034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
7134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
7234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <poll.h>
7334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
7434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
7534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SVR4
7634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/stropts.h>
7734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_MP_PROCFS
7834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_SYS_UIO_H
7934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <sys/uio.h>
8034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
8134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
8234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
83f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownextern char **environ;
84f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownextern int optind;
85f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownextern char *optarg;
8634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
8734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
88f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownint debug = 0, followfork = 0;
89f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownunsigned int ptrace_setoptions = 0;
90f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownint dtime = 0, xflag = 0, qflag = 0;
91f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Browncflag_t cflag = CFLAG_NONE;
92f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
93f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown/*
94f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * daemonized_tracer supports -D option.
95f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * With this option, strace forks twice.
96f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * Unlike normal case, with -D *grandparent* process exec's,
97f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * becoming a traced process. Child exits (this prevents traced process
98f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * from having children it doesn't expect to have), and grandchild
99f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * attaches to grandparent similarly to strace -p PID.
100f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * This allows for more transparent interaction in cases
101f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * when process and its parent are communicating via signals,
102f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * wait() etc. Without -D, strace process gets lodged in between,
103f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * disrupting parent<->child link.
104f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown */
105f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic bool daemonized_tracer = 0;
10634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
10734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project/* Sometimes we want to print only succeeding syscalls. */
10834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint not_failing_only = 0;
10934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
110f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int exit_code = 0;
111f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int strace_child = 0;
112f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
113f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic char *username = NULL;
11434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectuid_t run_uid;
11534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectgid_t run_gid;
11634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
11734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint acolumn = DEFAULT_ACOLUMN;
11834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint max_strlen = DEFAULT_STRLEN;
119f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic char *outfname = NULL;
12034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source ProjectFILE *outf;
121f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int curcol;
12234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb **tcbtab;
12334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectunsigned int nprocs, tcbtabsize;
124f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownconst char *progname;
12534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectextern char **environ;
12634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
127f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int detach(struct tcb *tcp, int sig);
128f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int trace(void);
129f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void cleanup(void);
130f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void interrupt(int sig);
13134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic sigset_t empty_set, blocked_set;
13234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
13334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_SIG_ATOMIC_T
13434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic volatile sig_atomic_t interrupted;
13534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* !HAVE_SIG_ATOMIC_T */
13634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic volatile int interrupted;
13734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_SIG_ATOMIC_T */
13834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
13934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
14034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
141f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic struct tcb *pfd2tcb(int pfd);
142f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void reaper(int sig);
143f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void rebuild_pollv(void);
14434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic struct pollfd *pollv;
14534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
14634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
14734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
148f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void proc_poll_open(void);
149f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void proc_poller(int pfd);
15034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
15134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct proc_pollfd {
15234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int fd;
15334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int revents;
15434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int pid;
15534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project};
15634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
15734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int poller_pid;
15834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int proc_poll_pipe[2] = { -1, -1 };
15934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
16034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_POLLABLE_PROCFS */
16134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
16234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_MP_PROCFS
16334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#define POLLWANT	POLLWRNORM
16434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
16534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#define POLLWANT	POLLPRI
16634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
16734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* USE_PROCFS */
16834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
16934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
17034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectusage(ofp, exitval)
17134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source ProjectFILE *ofp;
17234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint exitval;
17334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
17434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	fprintf(ofp, "\
175f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownusage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
17634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
17734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project              [command [arg ...]]\n\
178f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
17934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project              [command [arg ...]]\n\
18034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-c -- count time, calls, and errors for each syscall and report summary\n\
181f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown-C -- like -c but also print regular output while processes are running\n\
18234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-f -- follow forks, -ff -- with output into separate files\n\
18334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-F -- attempt to follow vforks, -h -- print help message\n\
18434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-i -- print instruction pointer at time of syscall\n\
18534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-q -- suppress messages about attaching, detaching, etc.\n\
18634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-T -- print time spent in each syscall, -V -- print version\n\
18834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
18934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
19034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-o file -- send trace output to FILE instead of stderr\n\
19434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-p pid -- trace process with process id PID, may be repeated\n\
196f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown-D -- run tracer process as a detached grandchild, not as parent\n\
19734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-u username -- run command as username handling setuid and/or setgid\n\
20034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-E var=val -- put var=val in the environment for command\n\
20134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-E var -- remove var from the environment for command\n\
20234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project" /* this is broken, so don't document it
20334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project-z -- print only succeeding syscalls\n\
20434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project  */
20534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	exit(exitval);
20734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
20834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
20934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SVR4
21034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef MIPS
21134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
21234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectfoobar()
21334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
21434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
21534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* MIPS */
21634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* SVR4 */
21734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
218f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown/* Glue for systems without a MMU that cannot provide fork() */
219f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef HAVE_FORK
220f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define strace_vforked 0
221f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else
222f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define strace_vforked 1
223f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define fork()         vfork()
224f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
225f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
226f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int
227f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownset_cloexec_flag(int fd)
228f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
229f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int     flags, newflags;
230f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
231f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
232f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
233f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
234f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, strerror(errno));
235f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return -1;
236f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
237f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
238f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	newflags = flags | FD_CLOEXEC;
239f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (flags == newflags)
240f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return 0;
241f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
242f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (fcntl(fd, F_SETFD, newflags) < 0)
243f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
244f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
245f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, strerror(errno));
246f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return -1;
247f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
248f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
249f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return 0;
250f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
251f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
252f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown/*
253f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * When strace is setuid executable, we have to swap uids
254f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * before and after filesystem and process management operations.
255f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown */
256f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void
257f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownswap_uid(void)
258f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
259f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifndef SVR4
260f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int euid = geteuid(), uid = getuid();
261f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
262f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (euid != uid && setreuid(euid, uid) < 0)
263f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
264f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: setreuid: %s\n",
265f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, strerror(errno));
266f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
267f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
268f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
269f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
270f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
271f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#if _LFS64_LARGEFILE
272f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define fopen_for_output fopen64
273f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else
274f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define fopen_for_output fopen
275f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
276f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
277f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic FILE *
278f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstrace_fopen(const char *path, const char *mode)
279f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
280f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	FILE *fp;
281f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
282f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	swap_uid();
283f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((fp = fopen_for_output(path, mode)) == NULL)
284f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: can't fopen '%s': %s\n",
285f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, path, strerror(errno));
286f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	swap_uid();
287f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (fp && set_cloexec_flag(fileno(fp)) < 0)
288f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
289f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fclose(fp);
290f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fp = NULL;
291f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
292f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return fp;
293f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
294f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
295f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int popen_pid = -1;
296f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
297f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifndef _PATH_BSHELL
298f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define _PATH_BSHELL "/bin/sh"
299f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
300f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
301f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown/*
302f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * We cannot use standard popen(3) here because we have to distinguish
303f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * popen child process from other processes we trace, and standard popen(3)
304f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * does not export its child's pid.
305f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown */
306f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic FILE *
307f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstrace_popen(const char *command)
308f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
309f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int     fds[2];
310f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
311f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	swap_uid();
312f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (pipe(fds) < 0)
313f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
314f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: pipe: %s\n",
315f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, strerror(errno));
316f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		swap_uid();
317f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return NULL;
318f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
319f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
320f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (set_cloexec_flag(fds[1]) < 0)
321f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
322f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		close(fds[0]);
323f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		close(fds[1]);
324f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		swap_uid();
325f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return NULL;
326f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
327f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
328f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((popen_pid = fork()) == -1)
329f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
330f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: fork: %s\n",
331f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, strerror(errno));
332f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		close(fds[0]);
333f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		close(fds[1]);
334f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		swap_uid();
335f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return NULL;
336f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
337f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
338f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (popen_pid)
339f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
340f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* parent */
341f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		close(fds[0]);
342f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		swap_uid();
343f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return fdopen(fds[1], "w");
344f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	} else
345f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	{
346f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* child */
347f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		close(fds[1]);
348f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
349f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		{
350f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			fprintf(stderr, "%s: dup2: %s\n",
351f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				progname, strerror(errno));
352f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			_exit(1);
353f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
354f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
355f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: execl: %s: %s\n",
356f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, _PATH_BSHELL, strerror(errno));
357f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		_exit(1);
358f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
359f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
360f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
361f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int
362f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownnewoutf(struct tcb *tcp)
363f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
364f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (outfname && followfork > 1) {
365f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		char name[520 + sizeof(int) * 3];
366f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		FILE *fp;
367f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
368f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sprintf(name, "%.512s.%u", outfname, tcp->pid);
369f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if ((fp = strace_fopen(name, "w")) == NULL)
370f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			return -1;
371f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->outf = fp;
372f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
373f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return 0;
374f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
375f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
376f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void
377f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstartup_attach(void)
378f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
379f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int tcbi;
380f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	struct tcb *tcp;
381f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
382f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/*
383f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * Block user interruptions as we would leave the traced
384f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * process stopped (process state T) if we would terminate in
385f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
386f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * We rely on cleanup () from this point on.
387f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 */
388f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (interactive)
389f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
390f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
391f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (daemonized_tracer) {
392f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		pid_t pid = fork();
393f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (pid < 0) {
394f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			_exit(1);
395f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
396f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (pid) { /* parent */
397f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
398f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Wait for child to attach to straced process
399f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * (our parent). Child SIGKILLs us after it attached.
400f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Parent's wait() is unblocked by our death,
401f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * it proceeds to exec the straced program.
402f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
403f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			pause();
404f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			_exit(0); /* paranoia */
405f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
406f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
407f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
408f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
409f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp = tcbtab[tcbi];
410f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
411f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			continue;
412f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
413f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (tcp->flags & TCB_CLONE_THREAD)
414f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			continue;
415f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
416f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Reinitialize the output since it may have changed. */
417f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->outf = outf;
418f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (newoutf(tcp) < 0)
419f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			exit(1);
420f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
421f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef USE_PROCFS
422f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (proc_open(tcp, 1) < 0) {
423f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			fprintf(stderr, "trouble opening proc file\n");
424f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			droptcb(tcp);
425f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			continue;
426f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
427f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else /* !USE_PROCFS */
428f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# ifdef LINUX
429f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (followfork && !daemonized_tracer) {
430f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
431f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			DIR *dir;
432f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
433f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			sprintf(procdir, "/proc/%d/task", tcp->pid);
434f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			dir = opendir(procdir);
435f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (dir != NULL) {
436f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				unsigned int ntid = 0, nerr = 0;
437f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				struct dirent *de;
438f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				int tid;
439f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				while ((de = readdir(dir)) != NULL) {
440f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					if (de->d_fileno == 0)
441f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						continue;
442f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					tid = atoi(de->d_name);
443f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					if (tid <= 0)
444f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						continue;
445f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					++ntid;
446f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
447f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						++nerr;
448f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					else if (tid != tcbtab[tcbi]->pid) {
449f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						tcp = alloctcb(tid);
450f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
451f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						tcbtab[tcbi]->nchildren++;
452f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						tcbtab[tcbi]->nclone_threads++;
453f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						tcp->parent = tcbtab[tcbi];
454f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					}
455f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					if (interactive) {
456f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						sigprocmask(SIG_SETMASK, &empty_set, NULL);
457f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						if (interrupted)
458f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown							return;
459f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
460f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					}
461f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
462f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				closedir(dir);
463f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				ntid -= nerr;
464f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (ntid == 0) {
465f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					perror("attach: ptrace(PTRACE_ATTACH, ...)");
466f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					droptcb(tcp);
467f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					continue;
468f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
469f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (!qflag) {
470f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					fprintf(stderr, ntid > 1
471f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown? "Process %u attached with %u threads - interrupt to quit\n"
472f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown: "Process %u attached - interrupt to quit\n",
473f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						tcbtab[tcbi]->pid, ntid);
474f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
475f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				continue;
476f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			} /* if (opendir worked) */
477f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		} /* if (-f) */
478f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# endif
479f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
480f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			perror("attach: ptrace(PTRACE_ATTACH, ...)");
481f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			droptcb(tcp);
482f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			continue;
483f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
484f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* INTERRUPTED is going to be checked at the top of TRACE.  */
485f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
486f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (daemonized_tracer) {
487f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
488f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * It is our grandparent we trace, not a -p PID.
489f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Don't want to just detach on exit, so...
490f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
491f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tcp->flags &= ~TCB_ATTACHED;
492f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
493f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Make parent go away.
494f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Also makes grandparent's wait() unblock.
495f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
496f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			kill(getppid(), SIGKILL);
497f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
498f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
499f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* !USE_PROCFS */
500f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (!qflag)
501f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			fprintf(stderr,
502f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				"Process %u attached - interrupt to quit\n",
503f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				tcp->pid);
504f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
505f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
506f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (interactive)
507f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sigprocmask(SIG_SETMASK, &empty_set, NULL);
508f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
509f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
510f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void
511f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstartup_child (char **argv)
512f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
513f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	struct stat statbuf;
514f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	const char *filename;
515f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	char pathname[MAXPATHLEN];
516f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int pid = 0;
517f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	struct tcb *tcp;
518f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
519f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	filename = argv[0];
520f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (strchr(filename, '/')) {
521f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (strlen(filename) > sizeof pathname - 1) {
522f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			errno = ENAMETOOLONG;
523f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			perror("strace: exec");
524f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			exit(1);
525f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
526f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		strcpy(pathname, filename);
527f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
528f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef USE_DEBUGGING_EXEC
529f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/*
530f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * Debuggers customarily check the current directory
531f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * first regardless of the path but doing that gives
532f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * security geeks a panic attack.
533f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 */
534f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	else if (stat(filename, &statbuf) == 0)
535f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		strcpy(pathname, filename);
536f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* USE_DEBUGGING_EXEC */
537f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	else {
538f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		const char *path;
539f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		int m, n, len;
540f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
541f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		for (path = getenv("PATH"); path && *path; path += m) {
542f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (strchr(path, ':')) {
543f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				n = strchr(path, ':') - path;
544f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				m = n + 1;
545f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
546f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			else
547f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				m = n = strlen(path);
548f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (n == 0) {
549f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (!getcwd(pathname, MAXPATHLEN))
550f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					continue;
551f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				len = strlen(pathname);
552f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
553f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			else if (n > sizeof pathname - 1)
554f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				continue;
555f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			else {
556f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				strncpy(pathname, path, n);
557f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				len = n;
558f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
559f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (len && pathname[len - 1] != '/')
560f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				pathname[len++] = '/';
561f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			strcpy(pathname + len, filename);
562f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (stat(pathname, &statbuf) == 0 &&
563f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    /* Accept only regular files
564f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			       with some execute bits set.
565f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			       XXX not perfect, might still fail */
566f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    S_ISREG(statbuf.st_mode) &&
567f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    (statbuf.st_mode & 0111))
568f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				break;
569f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
570f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
571f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (stat(pathname, &statbuf) < 0) {
572f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: %s: command not found\n",
573f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname, filename);
574f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
575f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
576f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	strace_child = pid = fork();
577f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (pid < 0) {
578f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		perror("strace: fork");
579f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		cleanup();
580f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
581f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
582f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
583f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
584f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	) {
585f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		pid = getpid();
586f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef USE_PROCFS
587f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (outf != stderr) close (fileno (outf));
588f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef MIPS
589f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Kludge for SGI, see proc_open for details. */
590f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sa.sa_handler = foobar;
591f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sa.sa_flags = 0;
592f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sigemptyset(&sa.sa_mask);
593f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		sigaction(SIGINT, &sa, NULL);
594f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* MIPS */
595f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifndef FREEBSD
596f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		pause();
597f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else /* FREEBSD */
598f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		kill(pid, SIGSTOP); /* stop HERE */
599f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* FREEBSD */
600f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else /* !USE_PROCFS */
601f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (outf!=stderr)
602f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			close(fileno (outf));
603f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
604f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (!daemonized_tracer) {
605f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
606f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				perror("strace: ptrace(PTRACE_TRACEME, ...)");
607f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				exit(1);
608f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
609f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (debug)
610f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				kill(pid, SIGSTOP);
611f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
612f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
613f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (username != NULL || geteuid() == 0) {
614f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			uid_t run_euid = run_uid;
615f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			gid_t run_egid = run_gid;
616f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
617f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (statbuf.st_mode & S_ISUID)
618f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				run_euid = statbuf.st_uid;
619f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (statbuf.st_mode & S_ISGID)
620f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				run_egid = statbuf.st_gid;
621f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
622f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
623f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * It is important to set groups before we
624f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * lose privileges on setuid.
625f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
626f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (username != NULL) {
627f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (initgroups(username, run_gid) < 0) {
628f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					perror("initgroups");
629f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					exit(1);
630f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
631f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (setregid(run_gid, run_egid) < 0) {
632f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					perror("setregid");
633f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					exit(1);
634f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
635f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (setreuid(run_uid, run_euid) < 0) {
636f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					perror("setreuid");
637f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					exit(1);
638f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
639f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
640f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
641f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		else
642f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			setreuid(run_uid, run_uid);
643f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
644f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (!daemonized_tracer) {
645f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
646f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Induce an immediate stop so that the parent
647f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * will resume us with PTRACE_SYSCALL and display
648f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * this execve call normally.
649f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Unless of course we're on a no-MMU system where
650f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * we vfork()-ed, so we cannot stop the child.
651f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
652f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (!strace_vforked)
653f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				kill(getpid(), SIGSTOP);
654f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		} else {
655f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			struct sigaction sv_sigchld;
656f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			sigaction(SIGCHLD, NULL, &sv_sigchld);
657f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
658f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Make sure it is not SIG_IGN, otherwise wait
659f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * will not block.
660f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
661f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			signal(SIGCHLD, SIG_DFL);
662f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/*
663f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Wait for grandchild to attach to us.
664f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * It kills child after that, and wait() unblocks.
665f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
666f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			alarm(3);
667f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			wait(NULL);
668f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			alarm(0);
669f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			sigaction(SIGCHLD, &sv_sigchld, NULL);
670f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
671f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* !USE_PROCFS */
672f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
673f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		execv(pathname, argv);
674f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		perror("strace: exec");
675f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		_exit(1);
676f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
677f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
678f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/* We are the tracer.  */
679f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
680f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (daemonized_tracer) {
681f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* We want subsequent startup_attach() to attach to it.  */
682f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->flags |= TCB_ATTACHED;
683f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
684f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef USE_PROCFS
685f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (proc_open(tcp, 0) < 0) {
686f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "trouble opening proc file\n");
687f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		cleanup();
688f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
689f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
690f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* USE_PROCFS */
691f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
692f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
693f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
694f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown/*
695f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
696f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
697f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown * and then see which options are supported by the kernel.
698f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown */
699f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int
700f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Browntest_ptrace_setoptions(void)
701f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
702f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int pid, expected_grandchild = 0, found_grandchild = 0;
703f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	const unsigned int test_options = PTRACE_O_TRACECLONE |
704f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					  PTRACE_O_TRACEFORK |
705f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					  PTRACE_O_TRACEVFORK;
706f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
707f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((pid = fork()) < 0)
708f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return -1;
709f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	else if (pid == 0) {
710f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
711f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			_exit(1);
712f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		kill(getpid(), SIGSTOP);
713f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		_exit(fork() < 0);
714f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
715f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
716f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	while (1) {
717f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		int status, tracee_pid;
718f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
719f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tracee_pid = wait(&status);
720f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (tracee_pid == -1) {
721f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (errno == EINTR)
722f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				continue;
723f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			else if (errno == ECHILD)
724f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				break;
725f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			perror("test_ptrace_setoptions");
726f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			return -1;
727f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
728f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (tracee_pid != pid) {
729f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			found_grandchild = tracee_pid;
730f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
731f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    errno != ESRCH)
732f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				kill(tracee_pid, SIGKILL);
733f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
734f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		else if (WIFSTOPPED(status)) {
735f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			switch (WSTOPSIG(status)) {
736f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			case SIGSTOP:
737f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (ptrace(PTRACE_SETOPTIONS, pid,
738f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					   NULL, test_options) < 0) {
739f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					kill(pid, SIGKILL);
740f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					return -1;
741f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
742f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				break;
743f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			case SIGTRAP:
744f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (status >> 16 == PTRACE_EVENT_FORK) {
745f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					long msg = 0;
746f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
747f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					if (ptrace(PTRACE_GETEVENTMSG, pid,
748f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						   NULL, (long) &msg) == 0)
749f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						expected_grandchild = msg;
750f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
751f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				break;
752f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
753f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
754f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    errno != ESRCH)
755f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				kill(pid, SIGKILL);
756f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
757f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
758f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (expected_grandchild && expected_grandchild == found_grandchild)
759f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		ptrace_setoptions |= test_options;
760f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return 0;
761f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
762f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
763f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
76434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint
765f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownmain(int argc, char *argv[])
76634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
76734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *tcp;
76834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int c, pid = 0;
769f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int optF = 0;
77034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct sigaction sa;
77134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
77234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	static char buf[BUFSIZ];
77334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
774f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	progname = argv[0] ? argv[0] : "strace";
775f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
77634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Allocate the initial tcbtab.  */
77734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcbtabsize = argc;	/* Surely enough for all -p args.  */
778f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
779f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: out of memory\n", progname);
780f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
781f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
782f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
783f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: out of memory\n", progname);
784f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
785f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
78634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
78734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
78834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
78934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	outf = stderr;
79034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	interactive = 1;
791f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	set_sortby(DEFAULT_SORTBY);
792f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	set_personality(DEFAULT_PERSONALITY);
79334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	qualify("trace=all");
79434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	qualify("abbrev=all");
79534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	qualify("verbose=all");
79634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	qualify("signal=all");
79734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	while ((c = getopt(argc, argv,
798f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		"+cCdfFhiqrtTvVxz"
799f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifndef USE_PROCFS
800f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		"D"
801f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
802f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		"a:e:o:O:p:s:S:u:E:")) != EOF) {
80334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		switch (c) {
80434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'c':
805f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (cflag == CFLAG_BOTH) {
806f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
807f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					progname);
808f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				exit(1);
809f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
810f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			cflag = CFLAG_ONLY_STATS;
811f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			break;
812f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		case 'C':
813f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (cflag == CFLAG_ONLY_STATS) {
814f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
815f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					progname);
816f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				exit(1);
817f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
818f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			cflag = CFLAG_BOTH;
81934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
82034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'd':
82134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			debug++;
82234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
823f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifndef USE_PROCFS
824f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		case 'D':
825f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			daemonized_tracer = 1;
82634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
827f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
82834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'F':
829f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			optF = 1;
830f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			break;
831f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		case 'f':
832f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			followfork++;
83334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
83434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'h':
83534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			usage(stdout, 0);
83634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
83734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'i':
83834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			iflag++;
83934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
84034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'q':
84134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			qflag++;
84234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
84334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'r':
84434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			rflag++;
84534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tflag++;
84634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
84734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 't':
84834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tflag++;
84934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
85034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'T':
85134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			dtime++;
85234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
85334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'x':
85434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			xflag++;
85534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
85634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'v':
85734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			qualify("abbrev=none");
85834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
85934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'V':
86034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
86134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(0);
86234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
86334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'z':
86434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			not_failing_only = 1;
86534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
86634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'a':
86734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			acolumn = atoi(optarg);
86834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
86934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'e':
87034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			qualify(optarg);
87134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
87234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'o':
87334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			outfname = strdup(optarg);
87434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
87534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'O':
87634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			set_overhead(atoi(optarg));
87734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
87834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'p':
87934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if ((pid = atoi(optarg)) <= 0) {
88034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "%s: Invalid process id: %s\n",
88134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					progname, optarg);
88234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
88334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
88434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (pid == getpid()) {
88534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
88634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
88734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
888f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tcp = alloc_tcb(pid, 0);
88934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->flags |= TCB_ATTACHED;
89034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			pflag_seen++;
89134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
89234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 's':
89334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			max_strlen = atoi(optarg);
89434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (max_strlen < 0) {
89534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr,
89634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					"%s: invalid -s argument: %s\n",
89734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					progname, optarg);
89834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
89934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
90034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
90134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'S':
90234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			set_sortby(optarg);
90334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
90434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'u':
90534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			username = strdup(optarg);
90634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
90734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 'E':
90834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (putenv(optarg) < 0) {
90934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "%s: out of memory\n",
91034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					progname);
91134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
91234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
91334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
91434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		default:
91534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			usage(stderr, 1);
91634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
91734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
91834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
91934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
920f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((optind == argc) == !pflag_seen)
92134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		usage(stderr, 1);
92234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
923f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (pflag_seen && daemonized_tracer) {
924f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr,
925f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			"%s: -D and -p are mutually exclusive options\n",
926f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname);
927f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
928f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
929f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
930f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (!followfork)
931f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		followfork = optF;
932f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
933f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (followfork > 1 && cflag) {
934f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr,
935f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			"%s: (-c or -C) and -ff are mutually exclusive options\n",
936f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname);
937f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
938f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
939f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
94034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* See if they want to run as another user. */
94134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (username != NULL) {
94234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		struct passwd *pent;
94334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
94434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (getuid() != 0 || geteuid() != 0) {
94534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr,
94634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				"%s: you must be root to use the -u option\n",
94734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				progname);
94834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
94934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
95034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if ((pent = getpwnam(username)) == NULL) {
95134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr, "%s: cannot find user `%s'\n",
952f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				progname, username);
95334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
95434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
95534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		run_uid = pent->pw_uid;
95634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		run_gid = pent->pw_gid;
95734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
95834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	else {
95934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		run_uid = getuid();
96034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		run_gid = getgid();
96134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
96234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
963f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
964f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (followfork) {
965f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (test_ptrace_setoptions() < 0) {
966f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			fprintf(stderr,
967f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				"Test for options supported by PTRACE_SETOPTIONS "
968f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				"failed, giving up using this feature.\n");
969f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			ptrace_setoptions = 0;
970f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
971f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (debug)
972f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			fprintf(stderr, "ptrace_setoptions = %#x\n",
973f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				ptrace_setoptions);
974f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
97534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
97634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
97734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Check if they want to redirect the output. */
97834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (outfname) {
97934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* See if they want to pipe the output. */
98034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (outfname[0] == '|' || outfname[0] == '!') {
98134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/*
98234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * We can't do the <outfname>.PID funny business
98334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * when using popen, so prohibit it.
98434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 */
98534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (followfork > 1) {
98634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "\
98734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project%s: piping the output and -ff are mutually exclusive options\n",
98834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					progname);
98934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
99034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
99134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
992f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if ((outf = strace_popen(outfname + 1)) == NULL)
99334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
99434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
995f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		else if (followfork <= 1 &&
996f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 (outf = strace_fopen(outfname, "w")) == NULL)
99734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
99834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
99934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
100034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
100134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		setvbuf(outf, buf, _IOLBF, BUFSIZ);
100234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (outfname && optind < argc) {
100334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		interactive = 0;
100434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		qflag = 1;
100534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
100634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1007f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/* Valid states here:
1008f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   optind < argc	pflag_seen	outfname	interactive
1009f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   1			0		0		1
1010f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   0			1		0		1
1011f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   1			0		1		0
1012f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   0			1		1		1
1013f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 */
101434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1015f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/* STARTUP_CHILD must be called before the signal handlers get
1016f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   installed below as they are inherited into the spawned process.
1017f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   Also we do not need to be protected by them as during interruption
1018f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
1019f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (!pflag_seen)
1020f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		startup_child(&argv[optind]);
102134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
102234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigemptyset(&empty_set);
102334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigemptyset(&blocked_set);
102434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_handler = SIG_IGN;
102534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigemptyset(&sa.sa_mask);
102634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_flags = 0;
102734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGTTOU, &sa, NULL);
102834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGTTIN, &sa, NULL);
102934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (interactive) {
103034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sigaddset(&blocked_set, SIGHUP);
103134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sigaddset(&blocked_set, SIGINT);
103234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sigaddset(&blocked_set, SIGQUIT);
103334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sigaddset(&blocked_set, SIGPIPE);
103434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sigaddset(&blocked_set, SIGTERM);
103534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sa.sa_handler = interrupt;
103634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SUNOS4
103734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* POSIX signals on sunos4.1 are a little broken. */
103834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sa.sa_flags = SA_INTERRUPT;
103934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* SUNOS4 */
104034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
104134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGHUP, &sa, NULL);
104234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGINT, &sa, NULL);
104334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGQUIT, &sa, NULL);
104434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGPIPE, &sa, NULL);
104534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGTERM, &sa, NULL);
104634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
104734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_handler = reaper;
104834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGCHLD, &sa, NULL);
104934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
105034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Make sure SIGCHLD has the default action so that waitpid
105134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   definitely works without losing track of children.  The user
105234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   should not have given us a bogus state to inherit, but he might
105334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   have.  Arguably we should detect SIG_IGN here and pass it on
105434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   to children, but probably noone really needs that.  */
105534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_handler = SIG_DFL;
105634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGCHLD, &sa, NULL);
105734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* USE_PROCFS */
105834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1059f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (pflag_seen || daemonized_tracer)
1060f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		startup_attach();
1061f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
106234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (trace() < 0)
106334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		exit(1);
106434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	cleanup();
1065f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	fflush(NULL);
1066f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (exit_code > 0xff) {
1067f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Child was killed by a signal, mimic that.  */
1068f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit_code &= 0xff;
1069f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		signal(exit_code, SIG_DFL);
1070f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		raise(exit_code);
1071f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Paranoia - what if this signal is not fatal?
1072f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		   Exit with 128 + signo then.  */
1073f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit_code += 128;
1074f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
1075f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	exit(exit_code);
107634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
107734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
107834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
1079f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownexpand_tcbtab(void)
108034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
108134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Allocate some more TCBs and expand the table.
108234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   We don't want to relocate the TCBs because our
108334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   callers have pointers and it would be a pain.
108434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   So tcbtab is a table of pointers.  Since we never
108534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   free the TCBs, we allocate a single chunk of many.  */
108634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb **newtab = (struct tcb **)
108734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
108834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
108934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						    sizeof *newtcbs);
109034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
109134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (newtab == NULL || newtcbs == NULL) {
1092f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
1093f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			progname);
1094f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		cleanup();
1095f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		exit(1);
109634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
109734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
109834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		newtab[i] = &newtcbs[i - tcbtabsize];
109934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcbtabsize *= 2;
110034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcbtab = newtab;
110134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
110234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
110334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb *
1104f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownalloc_tcb(int pid, int command_options_parsed)
110534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
110634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
110734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *tcp;
110834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1109f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (nprocs == tcbtabsize)
1110f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		expand_tcbtab();
1111f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
111234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < tcbtabsize; i++) {
111334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp = tcbtab[i];
111434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if ((tcp->flags & TCB_INUSE) == 0) {
111534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->pid = pid;
111634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->parent = NULL;
111734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->nchildren = 0;
111834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->nzombies = 0;
111934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_CLONE_THREAD
1120f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tcp->nclone_threads = 0;
112134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->nclone_waiting = 0;
112234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
112334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->flags = TCB_INUSE | TCB_STARTUP;
112434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->outf = outf; /* Initialise to current out file */
1125f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tcp->curcol = 0;
112634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->stime.tv_sec = 0;
112734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->stime.tv_usec = 0;
112834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->pfd = -1;
112934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			nprocs++;
1130f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (command_options_parsed)
1131f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				newoutf(tcp);
113234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return tcp;
113334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
113434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1135f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1136f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	cleanup();
1137f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	exit(1);
113834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
113934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
114034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
114134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint
1142f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownproc_open(struct tcb *tcp, int attaching)
114334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
114434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	char proc[32];
114534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	long arg;
114634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SVR4
114734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
114834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sysset_t syscalls;
114934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigset_t signals;
115034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	fltset_t faults;
115134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
115234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
115334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	static int last_pfd;
115434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
115534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
115634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_MP_PROCFS
115734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Open the process pseudo-files in /proc. */
115834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sprintf(proc, "/proc/%d/ctl", tcp->pid);
115934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
116034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("strace: open(\"/proc/...\", ...)");
116134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
116234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1163f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (set_cloexec_flag(tcp->pfd) < 0) {
116434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
116534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
116634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sprintf(proc, "/proc/%d/status", tcp->pid);
116734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
116834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("strace: open(\"/proc/...\", ...)");
116934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
117034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1171f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
117234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
117334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
117434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sprintf(proc, "/proc/%d/as", tcp->pid);
117534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
117634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("strace: open(\"/proc/...\", ...)");
117734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
117834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1179f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (set_cloexec_flag(tcp->pfd_as) < 0) {
118034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
118134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
118234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
118334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Open the process pseudo-file in /proc. */
118434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
118534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sprintf(proc, "/proc/%d", tcp->pid);
1186f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	tcp->pfd = open(proc, O_RDWR|O_EXCL);
118734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* FREEBSD */
118834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sprintf(proc, "/proc/%d/mem", tcp->pid);
1189f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	tcp->pfd = open(proc, O_RDWR);
119034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
1191f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (tcp->pfd < 0) {
119234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("strace: open(\"/proc/...\", ...)");
119334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
119434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1195f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (set_cloexec_flag(tcp->pfd) < 0) {
119634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
119734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
119834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
119934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
120034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sprintf(proc, "/proc/%d/regs", tcp->pid);
120134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
120234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("strace: open(\"/proc/.../regs\", ...)");
120334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
120434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
120534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (cflag) {
120634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sprintf(proc, "/proc/%d/status", tcp->pid);
120734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
120834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			perror("strace: open(\"/proc/.../status\", ...)");
120934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return -1;
121034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
121134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	} else
121234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->pfd_status = -1;
121334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
121434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	rebuild_pollv();
121534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (!attaching) {
121634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/*
121734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * Wait for the child to pause.  Because of a race
121834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * condition we have to poll for the event.
121934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 */
122034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		for (;;) {
122134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (IOCTL_STATUS (tcp) < 0) {
122234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				perror("strace: PIOCSTATUS");
122334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return -1;
122434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
122534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp->status.PR_FLAGS & PR_ASLEEP)
122634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    break;
122734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
122834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
122934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
123034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Stop the process so that we own the stop. */
123134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
123234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("strace: PIOCSTOP");
123334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
123434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
123534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
123634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef PIOCSET
123734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Set Run-on-Last-Close. */
123834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	arg = PR_RLC;
123934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
124034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOCSET PR_RLC");
124134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
124234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
124334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Set or Reset Inherit-on-Fork. */
124434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	arg = PR_FORK;
124534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
124634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOC{SET,RESET} PR_FORK");
124734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
124834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
124934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else  /* !PIOCSET */
125034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
125134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
125234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOCSRLC");
125334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
125434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
125534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
125634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOC{S,R}FORK");
125734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
125834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
125934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* FREEBSD */
126034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
126134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
126234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	        perror("PIOCGFL");
1263f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return -1;
126434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
126534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	arg &= ~PF_LINGER;
126634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1267f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		perror("PIOCSFL");
1268f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return -1;
126934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
127034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
127134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !PIOCSET */
127234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
127334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Enable all syscall entries we care about. */
127434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	premptyset(&syscalls);
127534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 1; i < MAX_QUALS; ++i) {
127634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (i > (sizeof syscalls) * CHAR_BIT) break;
127734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
127834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
127934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	praddset (&syscalls, SYS_execve);
128034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (followfork) {
128134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		praddset (&syscalls, SYS_fork);
128234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SYS_forkall
128334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		praddset (&syscalls, SYS_forkall);
128434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
128534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SYS_fork1
128634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		praddset (&syscalls, SYS_fork1);
128734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
128834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SYS_rfork1
128934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		praddset (&syscalls, SYS_rfork1);
129034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
129134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SYS_rforkall
129234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		praddset (&syscalls, SYS_rforkall);
129334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
129434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
129534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
129634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOCSENTRY");
129734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
129834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
129934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Enable the syscall exits. */
130034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
130134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOSEXIT");
130234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
130334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
130434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Enable signals we care about. */
130534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	premptyset(&signals);
130634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 1; i < MAX_QUALS; ++i) {
130734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (i > (sizeof signals) * CHAR_BIT) break;
130834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
130934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
131034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
131134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOCSTRACE");
131234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
131334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
131434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* Enable faults we care about */
131534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	premptyset(&faults);
131634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 1; i < MAX_QUALS; ++i) {
131734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (i > (sizeof faults) * CHAR_BIT) break;
131834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
131934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
132034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
132134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOCSFAULT");
132234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
132334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
132434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* FREEBSD */
132534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* set events flags. */
132634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	arg = S_SIG | S_SCE | S_SCX ;
132734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
132834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("PIOCBIS");
132934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
133034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
133134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
133234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (!attaching) {
133334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef MIPS
133434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/*
133534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * The SGI PRSABORT doesn't work for pause() so
133634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * we send it a caught signal to wake it up.
133734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 */
133834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		kill(tcp->pid, SIGINT);
133934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* !MIPS */
134034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef PRSABORT
134134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* The child is in a pause(), abort it. */
134234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		arg = PRSABORT;
134334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
134434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			perror("PIOCRUN");
134534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return -1;
134634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
134734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
134834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !MIPS*/
134934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
135034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* wake up the child if it received the SIGSTOP */
135134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		kill(tcp->pid, SIGCONT);
135234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
135334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		for (;;) {
135434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* Wait for the child to do something. */
135534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (IOCTL_WSTOP (tcp) < 0) {
135634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				perror("PIOCWSTOP");
135734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return -1;
135834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
135934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp->status.PR_WHY == PR_SYSENTRY) {
136034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->flags &= ~TCB_INSYSCALL;
136134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				get_scno(tcp);
136234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (known_scno(tcp) == SYS_execve)
136334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					break;
136434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
136534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* Set it running: maybe execve will be next. */
136634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
136734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			arg = 0;
136834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
136934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* FREEBSD */
137034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
137134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
137234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				perror("PIOCRUN");
137334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return -1;
137434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
137534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
137634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* handle the case where we "opened" the child before
137734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			   it did the kill -STOP */
137834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp->status.PR_WHY == PR_SIGNALLED &&
137934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    tcp->status.PR_WHAT == SIGSTOP)
138034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			        kill(tcp->pid, SIGCONT);
138134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
138234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
138334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
138434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
138534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* FREEBSD */
138634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	} else {
138734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (attaching < 2) {
138834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* We are attaching to an already running process.
138934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * Try to figure out the state of the process in syscalls,
139034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * to handle the first event well.
139134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * This is done by having a look at the "wchan" property of the
139234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * process, which tells where it is stopped (if it is). */
139334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			FILE * status;
139434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			char wchan[20]; /* should be enough */
139534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
139634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			sprintf(proc, "/proc/%d/status", tcp->pid);
139734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			status = fopen(proc, "r");
139834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (status &&
139934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
140034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
140134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
140234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    strcmp(wchan, "stopevent")) {
140334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/* The process is asleep in the middle of a syscall.
140434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   Fake the syscall entry event */
140534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
140634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->status.PR_WHY = PR_SYSENTRY;
140734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				trace_syscall(tcp);
140834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
140934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (status)
141034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fclose(status);
141134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		} /* otherwise it's a fork being followed */
141234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
141334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
141434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
141534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (proc_poll_pipe[0] != -1)
141634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		proc_poller(tcp->pfd);
141734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	else if (nprocs > 1) {
141834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		proc_poll_open();
141934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		proc_poller(last_pfd);
142034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		proc_poller(tcp->pfd);
142134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
142234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	last_pfd = tcp->pfd;
142334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_POLLABLE_PROCFS */
142434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return 0;
142534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
142634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
142734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* USE_PROCFS */
142834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
142934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb *
1430f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownpid2tcb(int pid)
143134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
143234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
1433f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1434f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (pid <= 0)
1435f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return NULL;
143634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
143734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < tcbtabsize; i++) {
1438f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		struct tcb *tcp = tcbtab[i];
1439f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
144034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return tcp;
144134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1442f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
144334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return NULL;
144434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
144534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
144634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
144734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
144834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic struct tcb *
1449f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownfirst_used_tcb(void)
1450f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
1451f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int i;
1452f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	struct tcb *tcp;
1453f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	for (i = 0; i < tcbtabsize; i++) {
1454f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp = tcbtab[i];
1455f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (tcp->flags & TCB_INUSE)
1456f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			return tcp;
1457f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
1458f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return NULL;
1459f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
1460f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1461f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic struct tcb *
146234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectpfd2tcb(pfd)
146334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint pfd;
146434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
146534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
146634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
146734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < tcbtabsize; i++) {
146834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		struct tcb *tcp = tcbtab[i];
146934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->pfd != pfd)
147034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
147134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_INUSE)
147234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return tcp;
147334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
147434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return NULL;
147534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
147634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
147734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* USE_PROCFS */
147834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
147934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
148034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectdroptcb(tcp)
148134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb *tcp;
148234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
148334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp->pid == 0)
148434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return;
148534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_CLONE_THREAD
148634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp->nclone_threads > 0) {
148734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* There are other threads left in this process, but this
148834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		   is the one whose PID represents the whole process.
148934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		   We need to keep this record around as a zombie until
149034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		   all the threads die.  */
149134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->flags |= TCB_EXITING;
149234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return;
149334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
149434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
149534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	nprocs--;
149634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcp->pid = 0;
149734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
149834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp->parent != NULL) {
149934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->parent->nchildren--;
150034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_CLONE_THREAD
150134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_CLONE_THREAD)
150234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->parent->nclone_threads--;
150334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
1504f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->parent->nzombies++;
1505f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
1506f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Update `tcp->parent->parent->nchildren' and the other fields
1507f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		   like NCLONE_DETACHED, only for zombie group leader that has
1508f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		   already reported and been short-circuited at the top of this
1509f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		   function.  The same condition as at the top of DETACH.  */
1510f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if ((tcp->flags & TCB_CLONE_THREAD) &&
1511f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		    tcp->parent->nclone_threads == 0 &&
1512f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		    (tcp->parent->flags & TCB_EXITING))
1513f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			droptcb(tcp->parent);
151434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
151534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->parent = NULL;
151634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
151734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
151834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcp->flags = 0;
151934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp->pfd != -1) {
152034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		close(tcp->pfd);
152134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->pfd = -1;
152234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
152334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->pfd_reg != -1) {
152434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		        close(tcp->pfd_reg);
152534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		        tcp->pfd_reg = -1;
152634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
152734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->pfd_status != -1) {
152834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			close(tcp->pfd_status);
152934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->pfd_status = -1;
153034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
153134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !FREEBSD */
153234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
153334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
153434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
153534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
153634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
153734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (outfname && followfork > 1 && tcp->outf)
153834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fclose(tcp->outf);
153934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
154034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcp->outf = 0;
154134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
154234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
154334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef USE_PROCFS
154434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
154534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
154634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectresume(tcp)
154734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb *tcp;
154834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
154934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp == NULL)
155034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
155134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
155234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (!(tcp->flags & TCB_SUSPENDED)) {
155334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
155434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
155534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
155634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcp->flags &= ~TCB_SUSPENDED;
155734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_CLONE_THREAD
155834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp->flags & TCB_CLONE_THREAD)
155934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->parent->nclone_waiting--;
156034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
156134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1562f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
156334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return -1;
156434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
156534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (!qflag)
156634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fprintf(stderr, "Process %u resumed\n", tcp->pid);
156734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return 0;
156834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
156934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1570f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int
1571f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownresume_from_tcp (struct tcb *tcp)
1572f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
1573f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int error = 0;
1574f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int resumed = 0;
1575f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1576f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/* XXX This won't always be quite right (but it never was).
1577f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   A waiter with argument 0 or < -1 is waiting for any pid in
1578f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   a particular pgrp, which this child might or might not be
1579f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   in.  The waiter will only wake up if it's argument is -1
1580f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   or if it's waiting for tcp->pid's pgrp.  It makes a
1581f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   difference to wake up a waiter when there might be more
1582f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   traced children, because it could get a false ECHILD
1583f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   error.  OTOH, if this was the last child in the pgrp, then
1584f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   it ought to wake up and get ECHILD.  We would have to
1585f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   search the system for all pid's in the pgrp to be sure.
1586f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1587f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	     && (t->waitpid == -1 ||
1588f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1589f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1590f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	*/
1591f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1592f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (tcp->parent &&
1593f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	    (tcp->parent->flags & TCB_SUSPENDED) &&
1594f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1595f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		error = resume(tcp->parent);
1596f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		++resumed;
1597f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
1598f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef TCB_CLONE_THREAD
1599f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1600f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Some other threads of our parent are waiting too.  */
1601f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		unsigned int i;
1602f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1603f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Resume all the threads that were waiting for this PID.  */
1604f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		for (i = 0; i < tcbtabsize; i++) {
1605f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			struct tcb *t = tcbtab[i];
1606f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (t->parent == tcp->parent && t != tcp
1607f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1608f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1609f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    && t->waitpid == tcp->pid) {
1610f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				error |= resume (t);
1611f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				++resumed;
1612f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
1613f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
1614f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (resumed == 0)
1615f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/* Noone was waiting for this PID in particular,
1616f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			   so now we might need to resume some wildcarders.  */
1617f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			for (i = 0; i < tcbtabsize; i++) {
1618f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				struct tcb *t = tcbtab[i];
1619f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (t->parent == tcp->parent && t != tcp
1620f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				    && ((t->flags
1621f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1622f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1623f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				    && t->waitpid <= 0
1624f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					) {
1625f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					error |= resume (t);
1626f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					break;
1627f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
1628f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
1629f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
1630f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
1631f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1632f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return error;
1633f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
1634f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
163534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !USE_PROCFS */
163634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1637f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown/* detach traced process; continue with sig
1638f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown   Never call DETACH twice on the same process as both unattached and
1639f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown   attached-unstopped processes give the same ESRCH.  For unattached process we
1640f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
164134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
164234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
164334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectdetach(tcp, sig)
164434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb *tcp;
164534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint sig;
164634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
164734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int error = 0;
164834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef LINUX
1649f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	int status, catch_sigstop;
1650f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	struct tcb *zombie = NULL;
1651f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1652f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/* If the group leader is lingering only because of this other
1653f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	   thread now dying, then detach the leader as well.  */
1654f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if ((tcp->flags & TCB_CLONE_THREAD) &&
1655f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	    tcp->parent->nclone_threads == 1 &&
1656f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	    (tcp->parent->flags & TCB_EXITING))
1657f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		zombie = tcp->parent;
165834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
165934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
166034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tcp->flags & TCB_BPTSET)
1661f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		clearbpt(tcp);
166234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
166334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef LINUX
166434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/*
166534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	 * Linux wrongly insists the child be stopped
166634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	 * before detaching.  Arghh.  We go through hoops
166734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	 * to make a clean break of things.
166834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	 */
166934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#if defined(SPARC)
167034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#undef PTRACE_DETACH
167134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#define PTRACE_DETACH PTRACE_SUNDETACH
167234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
1673f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	/*
1674f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1675f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * expected SIGSTOP.  We must catch exactly one as otherwise the
1676f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 * detached process would be left stopped (process state T).
1677f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	 */
1678f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	catch_sigstop = (tcp->flags & TCB_STARTUP);
167934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
168034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* On a clear day, you can see forever. */
168134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
168234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	else if (errno != ESRCH) {
168334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* Shouldn't happen. */
168434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("detach: ptrace(PTRACE_DETACH, ...)");
168534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1686f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1687f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown							  : tcp->pid),
1688f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			   tcp->pid, 0) < 0) {
168934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (errno != ESRCH)
169034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			perror("detach: checking sanity");
169134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1692f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1693f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					      ? tcp->parent->pid : tcp->pid),
1694f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					     tcp->pid, SIGSTOP) < 0) {
169534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (errno != ESRCH)
169634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			perror("detach: stopping child");
169734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
1698f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	else
1699f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		catch_sigstop = 1;
1700f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (catch_sigstop) {
170134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		for (;;) {
170234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef __WALL
170334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
170434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (errno == ECHILD) /* Already gone.  */
170534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					break;
170634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (errno != EINVAL) {
170734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					perror("detach: waiting");
170834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					break;
170934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
171034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* __WALL */
171134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/* No __WALL here.  */
171234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (waitpid(tcp->pid, &status, 0) < 0) {
171334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					if (errno != ECHILD) {
171434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						perror("detach: waiting");
171534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						break;
171634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					}
171734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef __WCLONE
171834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					/* If no processes, try clones.  */
171934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					if (wait4(tcp->pid, &status, __WCLONE,
172034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						  NULL) < 0) {
172134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						if (errno != ECHILD)
172234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project							perror("detach: waiting");
172334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						break;
172434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					}
172534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* __WCLONE */
172634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
172734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef __WALL
172834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
172934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
173034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (!WIFSTOPPED(status)) {
173134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/* Au revoir, mon ami. */
173234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
173334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
173434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (WSTOPSIG(status) == SIGSTOP) {
1735f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				ptrace_restart(PTRACE_DETACH, tcp, sig);
173634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
173734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
1738f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			error = ptrace_restart(PTRACE_CONT, tcp,
1739f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					WSTOPSIG(status) == SIGTRAP ? 0
1740f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					: WSTOPSIG(status));
1741f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (error < 0)
174234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
174334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
174434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
174534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* LINUX */
174634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
174734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#if defined(SUNOS4)
174834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
174934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (sig && kill(tcp->pid, sig) < 0)
175034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("detach: kill");
175134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sig = 0;
1752f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
175334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* SUNOS4 */
175434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
175534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef USE_PROCFS
1756f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	error |= resume_from_tcp (tcp);
175734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
175834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
175934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (!qflag)
176034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fprintf(stderr, "Process %u detached\n", tcp->pid);
176134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
176234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	droptcb(tcp);
1763f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
1764f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
1765f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (zombie != NULL) {
1766f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* TCP no longer exists therefore you must not detach () it.  */
1767f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		droptcb(zombie);
1768f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
1769f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
1770f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
177134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return error;
177234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
177334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
177434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
177534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
1776f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void reaper(int sig)
177734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
177834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int pid;
177934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int status;
178034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
178134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
178234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
178334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
178434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
178534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* USE_PROCFS */
178634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
178734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
178834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectcleanup()
178934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
179034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
179134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *tcp;
179234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
179334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < tcbtabsize; i++) {
179434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp = tcbtab[i];
179534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (!(tcp->flags & TCB_INUSE))
179634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
179734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (debug)
179834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr,
179934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				"cleanup: looking at pid %u\n", tcp->pid);
180034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp_last &&
180134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1802f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tprintf(" <unfinished ...>");
1803f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			printtrailer();
180434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
180534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_ATTACHED)
180634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			detach(tcp, 0);
180734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		else {
180834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			kill(tcp->pid, SIGCONT);
180934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			kill(tcp->pid, SIGTERM);
181034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
181134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
181234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (cflag)
181334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		call_summary(outf);
181434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
181534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
181634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
181734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectinterrupt(sig)
181834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint sig;
181934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
182034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	interrupted = 1;
182134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
182234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
182334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_STRERROR
182434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
182534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#if !HAVE_DECL_SYS_ERRLIST
182634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectextern int sys_nerr;
182734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectextern char *sys_errlist[];
182834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* HAVE_DECL_SYS_ERRLIST */
182934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
183034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectconst char *
183134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstrerror(errno)
183234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint errno;
183334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
183434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	static char buf[64];
183534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
183634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (errno < 1 || errno >= sys_nerr) {
183734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sprintf(buf, "Unknown error %d", errno);
183834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return buf;
183934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
184034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return sys_errlist[errno];
184134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
184234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
184334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* HAVE_STERRROR */
184434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
184534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_STRSIGNAL
184634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
184734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
184834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectextern char *sys_siglist[];
184934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
185034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
185134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectextern char *_sys_siglist[];
185234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
185334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
185434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectconst char *
185534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstrsignal(sig)
185634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint sig;
185734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
185834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	static char buf[64];
185934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
186034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (sig < 1 || sig >= NSIG) {
186134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sprintf(buf, "Unknown signal %d", sig);
186234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return buf;
186334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
186434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE__SYS_SIGLIST
186534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return _sys_siglist[sig];
186634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
186734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return sys_siglist[sig];
186834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
186934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
187034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
187134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* HAVE_STRSIGNAL */
187234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
187334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef USE_PROCFS
187434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
187534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
187634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectrebuild_pollv()
187734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
187834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i, j;
187934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
188034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (pollv != NULL)
188134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		free (pollv);
188234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
188334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (pollv == NULL) {
188434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fprintf(stderr, "%s: out of memory\n", progname);
188534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		exit(1);
188634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
188734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
188834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = j = 0; i < tcbtabsize; i++) {
188934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		struct tcb *tcp = tcbtab[i];
189034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (!(tcp->flags & TCB_INUSE))
189134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
189234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		pollv[j].fd = tcp->pfd;
189334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		pollv[j].events = POLLWANT;
189434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		j++;
189534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
189634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (j != nprocs) {
189734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fprintf(stderr, "strace: proc miscount\n");
189834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		exit(1);
189934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
190034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
190134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
190234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
190334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
190434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
190534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectproc_poll_open()
190634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
190734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
190834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
190934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (pipe(proc_poll_pipe) < 0) {
191034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("pipe");
191134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		exit(1);
191234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
191334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < 2; i++) {
1914f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
191534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
191634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
191734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
191834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
191934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
192034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
192134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectproc_poll(pollv, nfds, timeout)
192234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct pollfd *pollv;
192334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint nfds;
192434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint timeout;
192534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
192634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
192734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int n;
192834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct proc_pollfd pollinfo;
192934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
193034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
193134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return n;
193234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (n != sizeof(struct proc_pollfd)) {
193334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		fprintf(stderr, "panic: short read: %d\n", n);
193434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		exit(1);
193534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
193634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < nprocs; i++) {
193734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (pollv[i].fd == pollinfo.fd)
193834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			pollv[i].revents = pollinfo.revents;
193934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		else
194034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			pollv[i].revents = 0;
194134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
194234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	poller_pid = pollinfo.pid;
194334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return 1;
194434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
194534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
194634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
194734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectwakeup_handler(sig)
194834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint sig;
194934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
195034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
195134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
195234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic void
195334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectproc_poller(pfd)
195434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint pfd;
195534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
195634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct proc_pollfd pollinfo;
195734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct sigaction sa;
195834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigset_t blocked_set, empty_set;
195934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i;
196034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int n;
196134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct rlimit rl;
196234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
196334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct procfs_status pfs;
196434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
196534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
196634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	switch (fork()) {
196734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	case -1:
196834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("fork");
1969f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		_exit(1);
197034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	case 0:
197134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		break;
197234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	default:
197334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		return;
197434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
197534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
197634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
197734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_flags = 0;
197834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigemptyset(&sa.sa_mask);
197934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGHUP, &sa, NULL);
198034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGINT, &sa, NULL);
198134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGQUIT, &sa, NULL);
198234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGPIPE, &sa, NULL);
198334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGTERM, &sa, NULL);
198434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sa.sa_handler = wakeup_handler;
198534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaction(SIGUSR1, &sa, NULL);
198634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigemptyset(&blocked_set);
198734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigaddset(&blocked_set, SIGUSR1);
198834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
198934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	sigemptyset(&empty_set);
199034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
199134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
199234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		perror("getrlimit(RLIMIT_NOFILE, ...)");
1993f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		_exit(1);
199434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
199534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	n = rl.rlim_cur;
199634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < n; i++) {
199734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (i != pfd && i != proc_poll_pipe[1])
199834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			close(i);
199934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
200034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
200134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	pollinfo.fd = pfd;
200234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	pollinfo.pid = getpid();
200334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (;;) {
200434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
2005f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2006f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else
2007f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2008f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
200934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		{
201034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			switch (errno) {
201134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case EINTR:
201234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
201334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case EBADF:
201434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pollinfo.revents = POLLERR;
201534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
201634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case ENOENT:
201734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pollinfo.revents = POLLHUP;
201834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
201934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			default:
202034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				perror("proc_poller: PIOCWSTOP");
202134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
202234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
202334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			_exit(0);
202434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
202534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		pollinfo.revents = POLLWANT;
202634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
202734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		sigsuspend(&empty_set);
202834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
202934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
203034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
203134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_POLLABLE_PROCFS */
203234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
203334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
203434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectchoose_pfd()
203534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
203634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int i, j;
203734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *tcp;
203834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
203934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	static int last;
204034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
204134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (followfork < 2 &&
204234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	    last < nprocs && (pollv[last].revents & POLLWANT)) {
204334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/*
204434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * The previous process is ready to run again.  We'll
204534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * let it do so if it is currently in a syscall.  This
204634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 * heuristic improves the readability of the trace.
204734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		 */
204834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp = pfd2tcb(pollv[last].fd);
204934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp && (tcp->flags & TCB_INSYSCALL))
205034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return pollv[last].fd;
205134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
205234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
205334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (i = 0; i < nprocs; i++) {
205434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* Let competing children run round robin. */
205534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		j = (i + last + 1) % nprocs;
205634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (pollv[j].revents & (POLLHUP | POLLERR)) {
205734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp = pfd2tcb(pollv[j].fd);
205834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (!tcp) {
205934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "strace: lost proc\n");
206034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
206134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
206234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			droptcb(tcp);
206334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return -1;
206434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
206534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (pollv[j].revents & POLLWANT) {
206634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			last = j;
206734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return pollv[j].fd;
206834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
206934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
207034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	fprintf(stderr, "strace: nothing ready\n");
207134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	exit(1);
207234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
207334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
207434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
207534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projecttrace()
207634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
207734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef POLL_HACK
207834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *in_syscall = NULL;
207934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
208034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *tcp;
208134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int pfd;
208234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int what;
208334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int ioctl_result = 0, ioctl_errno = 0;
208434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	long arg;
208534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
208634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	for (;;) {
208734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (interactive)
208834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			sigprocmask(SIG_SETMASK, &empty_set, NULL);
208934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
209034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (nprocs == 0)
209134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
209234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
209334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		switch (nprocs) {
209434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 1:
209534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
209634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (proc_poll_pipe[0] == -1) {
209734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
2098f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				tcp = first_used_tcb();
209934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (!tcp)
210034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					continue;
210134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pfd = tcp->pfd;
210234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (pfd == -1)
210334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					continue;
210434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				break;
210534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
210634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
210734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* fall through ... */
210834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_POLLABLE_PROCFS */
210934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		default:
211034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_POLLABLE_PROCFS
211134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef POLL_HACK
211234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		        /* On some systems (e.g. UnixWare) we get too much ugly
211334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			   "unfinished..." stuff when multiple proceses are in
211434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			   syscalls.  Here's a nasty hack */
211534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
211634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (in_syscall) {
211734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				struct pollfd pv;
211834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp = in_syscall;
211934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				in_syscall = NULL;
212034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pv.fd = tcp->pfd;
212134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pv.events = POLLWANT;
212234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if ((what = poll (&pv, 1, 1)) < 0) {
212334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					if (interrupted)
212434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						return 0;
212534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					continue;
212634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
212734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				else if (what == 1 && pv.revents & POLLWANT) {
212834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					goto FOUND;
212934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
213034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
213134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
213234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
213334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (poll(pollv, nprocs, INFTIM) < 0) {
213434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (interrupted)
213534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					return 0;
213634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
213734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
213834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* !HAVE_POLLABLE_PROCFS */
213934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
214034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (interrupted)
214134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					return 0;
214234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
214334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
214434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_POLLABLE_PROCFS */
214534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			pfd = choose_pfd();
214634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (pfd == -1)
214734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
214834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
214934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
215034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
215134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* Look up `pfd' in our table. */
215234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if ((tcp = pfd2tcb(pfd)) == NULL) {
215334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr, "unknown pfd: %u\n", pfd);
215434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
215534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
215634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef POLL_HACK
215734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	FOUND:
215834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
215934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* Get the status of the process. */
216034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (!interrupted) {
216134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
216234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			ioctl_result = IOCTL_WSTOP (tcp);
216334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* FREEBSD */
216434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* Thanks to some scheduling mystery, the first poller
216534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			   sometimes waits for the already processed end of fork
216634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			   event. Doing a non blocking poll here solves the problem. */
216734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (proc_poll_pipe[0] != -1)
216834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				ioctl_result = IOCTL_STATUS (tcp);
216934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			else
2170f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				ioctl_result = IOCTL_WSTOP (tcp);
217134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* FREEBSD */
217234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			ioctl_errno = errno;
217334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef HAVE_POLLABLE_PROCFS
217434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (proc_poll_pipe[0] != -1) {
217534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (ioctl_result < 0)
217634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					kill(poller_pid, SIGKILL);
217734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				else
217834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					kill(poller_pid, SIGUSR1);
217934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
218034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !HAVE_POLLABLE_PROCFS */
218134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
218234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (interrupted)
218334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return 0;
218434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
218534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (interactive)
218634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
218734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
218834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (ioctl_result < 0) {
218934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* Find out what happened if it failed. */
219034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			switch (ioctl_errno) {
219134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case EINTR:
219234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case EBADF:
219334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
219434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
219534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case ENOTTY:
219634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
219734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case ENOENT:
219834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				droptcb(tcp);
219934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
220034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			default:
220134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				perror("PIOCWSTOP");
220234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
220334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
220434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
220534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
220634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
220734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
220834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* discard first event for a syscall we never entered */
220934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			IOCTL (tcp->pfd, PIOCRUN, 0);
221034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
221134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
221234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
221334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
221434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* clear the just started flag */
221534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tcp->flags &= ~TCB_STARTUP;
221634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
221734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* set current output file */
221834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		outf = tcp->outf;
2219f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		curcol = tcp->curcol;
222034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
222134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (cflag) {
222234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			struct timeval stime;
222334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
222434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			char buf[1024];
222534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			int len;
222634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
222734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
222834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				buf[len] = '\0';
222934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				sscanf(buf,
223034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
223134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				       &stime.tv_sec, &stime.tv_usec);
223234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			} else
223334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				stime.tv_sec = stime.tv_usec = 0;
223434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* !FREEBSD */
223534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			stime.tv_sec = tcp->status.pr_stime.tv_sec;
223634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
223734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !FREEBSD */
223834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tv_sub(&tcp->dtime, &stime, &tcp->stime);
223934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->stime = stime;
224034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
224134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		what = tcp->status.PR_WHAT;
224234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		switch (tcp->status.PR_WHY) {
224334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
224434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case PR_REQUESTED:
224534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
224634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->status.PR_WHY = PR_SYSENTRY;
224734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (trace_syscall(tcp) < 0) {
224834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					fprintf(stderr, "syscall trouble\n");
224934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					exit(1);
225034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
225134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
225234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
225334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !FREEBSD */
225434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case PR_SYSENTRY:
225534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef POLL_HACK
225634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		        in_syscall = tcp;
225734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
225834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case PR_SYSEXIT:
225934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (trace_syscall(tcp) < 0) {
226034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "syscall trouble\n");
226134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
226234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
226334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
226434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case PR_SIGNALLED:
2265f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (cflag != CFLAG_ONLY_STATS
2266f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    && (qual_flags[what] & QUAL_SIGNAL)) {
226734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				printleader(tcp);
226834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tprintf("--- %s (%s) ---",
226934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					signame(what), strsignal(what));
2270f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				printtrailer();
227134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef PR_INFO
227234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (tcp->status.PR_INFO.si_signo == what) {
227334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					printleader(tcp);
227434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					tprintf("    siginfo=");
227534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					printsiginfo(&tcp->status.PR_INFO, 1);
2276f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					printtrailer();
227734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
227834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
227934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
228034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
228134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case PR_FAULTED:
2282f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (cflag != CFLAGS_ONLY_STATS
2283f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    && (qual_flags[what] & QUAL_FAULT)) {
228434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				printleader(tcp);
228534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tprintf("=== FAULT %d ===", what);
2286f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				printtrailer();
228734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
228834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
228934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef FREEBSD
229034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		case 0: /* handle case we polled for nothing */
2291f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			continue;
229234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
229334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		default:
229434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
229534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
229634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			break;
229734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
2298f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Remember current print column before continuing. */
2299f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->curcol = curcol;
230034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		arg = 0;
230134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifndef FREEBSD
2302f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
230334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
2304f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
230534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
2306f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		{
230734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			perror("PIOCRUN");
230834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			exit(1);
230934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
231034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
231134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return 0;
231234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
231334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
231434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else /* !USE_PROCFS */
231534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
231634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_GROUP_EXITING
231734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project/* Handle an exit detach or death signal that is taking all the
231834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project   related clone threads with it.  This is called in three circumstances:
231934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
232034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project   SIG == 0	Continuing TCP will perform an exit_group syscall.
232134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project   SIG == other	Continuing TCP with SIG will kill the process.
232234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project*/
232334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
232434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projecthandle_group_exit(struct tcb *tcp, int sig)
232534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
232634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	/* We need to locate our records of all the clone threads
232734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	   related to TCP, either its children or siblings.  */
2328f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	struct tcb *leader = NULL;
2329f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
2330f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (tcp->flags & TCB_CLONE_THREAD)
2331f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		leader = tcp->parent;
233234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
233334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (sig < 0) {
2334f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (leader != NULL && leader != tcp
2335f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 && !(leader->flags & TCB_GROUP_EXITING)
2336f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 && !(tcp->flags & TCB_STARTUP)
2337f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		) {
233834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr,
233934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				"PANIC: handle_group_exit: %d leader %d\n",
234034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->pid, leader ? leader->pid : -1);
2341f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
2342f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* TCP no longer exists therefore you must not detach() it.  */
2343f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifndef USE_PROCFS
2344f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		resume_from_tcp(tcp);
2345f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
234634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		droptcb(tcp);	/* Already died.  */
234734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
234834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	else {
2349f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Mark that we are taking the process down.  */
2350f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
235134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_ATTACHED) {
235234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			detach(tcp, sig);
235334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (leader != NULL && leader != tcp)
2354f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				leader->flags |= TCB_GROUP_EXITING;
2355f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		} else {
2356f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2357f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				cleanup();
2358f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				return -1;
2359f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
2360f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (leader != NULL) {
2361f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				leader->flags |= TCB_GROUP_EXITING;
2362f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (leader != tcp)
2363f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					droptcb(tcp);
2364f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
236534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* The leader will report to us as parent now,
236634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			   and then we'll get to the SIG==-1 case.  */
236734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return 0;
236834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
236934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
237034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
237134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return 0;
237234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
237334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
237434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2375f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
2376f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic int
2377f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownhandle_ptrace_event(int status, struct tcb *tcp)
2378f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
2379f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (status >> 16 == PTRACE_EVENT_VFORK ||
2380f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	    status >> 16 == PTRACE_EVENT_CLONE ||
2381f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	    status >> 16 == PTRACE_EVENT_FORK) {
2382f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		long childpid;
2383f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
2384f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2385f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (errno != ESRCH) {
2386f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				fprintf(stderr, "\
2387f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2388f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					progname);
2389f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				cleanup();
2390f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				exit(1);
2391f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
2392f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			return -1;
2393f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
2394f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		return handle_new_child(tcp, childpid, 0);
2395f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	}
2396f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return 1;
2397f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}
2398f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
2399f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
240034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstatic int
240134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projecttrace()
240234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
240334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int pid;
240434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int wait_errno;
240534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int status;
240634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct tcb *tcp;
240734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef LINUX
240834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct rusage ru;
240934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef __WALL
241034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	static int wait4_options = __WALL;
241134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
241234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* LINUX */
241334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
241434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	while (nprocs != 0) {
2415f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (interrupted)
2416f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			return 0;
241734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (interactive)
241834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			sigprocmask(SIG_SETMASK, &empty_set, NULL);
241934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef LINUX
242034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef __WALL
242134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
242234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
242334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* this kernel does not support __WALL */
242434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			wait4_options &= ~__WALL;
242534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			errno = 0;
242634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			pid = wait4(-1, &status, wait4_options,
242734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					cflag ? &ru : NULL);
242834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
242934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
243034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/* most likely a "cloned" process */
243134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			pid = wait4(-1, &status, __WCLONE,
243234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					cflag ? &ru : NULL);
243334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (pid == -1) {
243434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "strace: clone wait4 "
243534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						"failed: %s\n", strerror(errno));
243634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
243734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
243834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
243934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
244034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* __WALL */
244134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* LINUX */
244234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef SUNOS4
244334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		pid = wait(&status);
244434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* SUNOS4 */
244534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		wait_errno = errno;
244634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (interactive)
244734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
244834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
244934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (pid == -1) {
245034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			switch (wait_errno) {
245134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case EINTR:
245234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
245334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			case ECHILD:
245434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/*
245534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 * We would like to verify this case
245634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 * but sometimes a race in Solbourne's
245734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 * version of SunOS sometimes reports
245834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 * ECHILD before sending us SIGCHILD.
245934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 */
246034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return 0;
246134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			default:
246234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				errno = wait_errno;
246334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				perror("strace: wait");
246434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return -1;
246534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
246634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
2467f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (pid == popen_pid) {
2468f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (WIFEXITED(status) || WIFSIGNALED(status))
2469f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				popen_pid = -1;
2470f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			continue;
2471f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
247234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (debug)
247334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
247434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
247534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* Look up `pid' in our table. */
247634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if ((tcp = pid2tcb(pid)) == NULL) {
247734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef LINUX
2478f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (followfork) {
247934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/* This is needed to go with the CLONE_PTRACE
248034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   changes in process.c/util.c: we might see
248134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   the child's initial trap before we see the
248234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   parent return from the clone syscall.
248334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   Leave the child suspended until the parent
248434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   returns from its system call.  Only then
248534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   will we have the association of parent and
248634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   child so that we know how to do clearbpt
248734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   in the child.  */
2488f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				tcp = alloctcb(pid);
248934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
249034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (!qflag)
249134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					fprintf(stderr, "\
249234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source ProjectProcess %d attached (waiting for parent)\n",
249334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						pid);
249434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
249534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			else
249634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/* This can happen if a clone call used
249734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				   CLONE_PTRACE itself.  */
249834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
249934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			{
250034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "unknown pid: %u\n", pid);
250134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (WIFSTOPPED(status))
250234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
250334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				exit(1);
250434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
250534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
250634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		/* set current output file */
250734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		outf = tcp->outf;
2508f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		curcol = tcp->curcol;
250934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (cflag) {
251034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef LINUX
251134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
251234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->stime = ru.ru_stime;
251334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !LINUX */
251434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
251534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
251634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_SUSPENDED) {
251734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/*
251834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * Apparently, doing any ptrace() call on a stopped
251934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * process, provokes the kernel to report the process
252034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * status again on a subsequent wait(), even if the
252134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * process has not been actually restarted.
252234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * Since we have inspected the arguments of suspended
252334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * processes we end up here testing for this case.
252434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 */
252534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
252634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
252734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (WIFSIGNALED(status)) {
2528f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (pid == strace_child)
2529f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				exit_code = 0x100 | WTERMSIG(status);
2530f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (cflag != CFLAG_ONLY_STATS
253134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
253234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				printleader(tcp);
253334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tprintf("+++ killed by %s %s+++",
253434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					signame(WTERMSIG(status)),
253534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef WCOREDUMP
253634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					WCOREDUMP(status) ? "(core dumped) " :
253734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
253834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					"");
2539f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				printtrailer();
254034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
254134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_GROUP_EXITING
254234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			handle_group_exit(tcp, -1);
254334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
254434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			droptcb(tcp);
254534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
254634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
254734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
254834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (WIFEXITED(status)) {
2549f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (pid == strace_child)
2550f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				exit_code = WEXITSTATUS(status);
255134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (debug)
2552f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2553f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
255434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_GROUP_EXITING
2555f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
2556f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			    && !(tcp->flags & TCB_GROUP_EXITING)
255734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
2558f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			) {
255934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr,
2560f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					"PANIC: attached pid %u exited with %d\n",
2561f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					pid, WEXITSTATUS(status));
2562f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
256334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp == tcp_last) {
2564f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
256534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					tprintf(" <unfinished ... exit status %d>\n",
256634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project						WEXITSTATUS(status));
256734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp_last = NULL;
256834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
256934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_GROUP_EXITING
257034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			handle_group_exit(tcp, -1);
257134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
257234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			droptcb(tcp);
257334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
257434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
257534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
257634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (!WIFSTOPPED(status)) {
257734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
257834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			droptcb(tcp);
257934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
258034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
258134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (debug)
258234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			fprintf(stderr, "pid %u stopped, [%s]\n",
258334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pid, signame(WSTOPSIG(status)));
258434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2585f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (ptrace_setoptions && (status >> 16)) {
2586f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (handle_ptrace_event(status, tcp) != 1)
2587f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				goto tracing;
2588f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
2589f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown
2590f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/*
2591f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 * Interestingly, the process may stop
2592f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 * with STOPSIG equal to some other signal
2593f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 * than SIGSTOP if we happend to attach
2594f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 * just before the process takes a signal.
2595f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 * A no-MMU vforked child won't send up a signal,
2596f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 * so skip the first (lost) execve notification.
2597f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		 */
2598f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if ((tcp->flags & TCB_STARTUP) &&
2599f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
260034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			/*
260134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * This flag is there to keep us in sync.
260234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * Next time this process stops it should
260334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 * really be entering a system call.
260434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			 */
260534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->flags &= ~TCB_STARTUP;
2606f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (tcp->flags & TCB_BPTSET) {
260734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/*
2608f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				 * One example is a breakpoint inherited from
2609f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				 * parent through fork ().
261034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 */
261134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
261234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					droptcb(tcp);
261334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					cleanup();
261434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					return -1;
261534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
261634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
2617f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX
2618f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (followfork && (tcp->parent == NULL) && ptrace_setoptions)
2619f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (ptrace(PTRACE_SETOPTIONS, tcp->pid,
2620f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					   NULL, ptrace_setoptions) < 0 &&
2621f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				    errno != ESRCH)
2622f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					ptrace_setoptions = 0;
2623f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif
262434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			goto tracing;
262534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
262634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
262734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (WSTOPSIG(status) != SIGTRAP) {
262834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (WSTOPSIG(status) == SIGSTOP &&
262934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					(tcp->flags & TCB_SIGTRAPPED)) {
263034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				/*
263134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 * Trapped attempt to block SIGTRAP
263234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 * Hope we are back in control now.
263334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				 */
263434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2635f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
263634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					cleanup();
263734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					return -1;
263834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				}
263934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
264034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
2641f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (cflag != CFLAG_ONLY_STATS
264234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2643f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				siginfo_t si;
2644f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
2645f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				long pc = 0;
2646f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				long psr = 0;
264734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2648f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				upeek(tcp, PT_CR_IPSR, &psr);
2649f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				upeek(tcp, PT_CR_IIP, &pc);
265034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2651f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define PSR_RI	41
265234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				pc += (psr >> PSR_RI) & 0x3;
2653f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define PC_FORMAT_STR	" @ %lx"
2654f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define PC_FORMAT_ARG	pc
2655f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#else
2656f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define PC_FORMAT_STR	"%s"
2657f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown# define PC_FORMAT_ARG	""
265834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
265934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				printleader(tcp);
2660f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2661f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					tprintf("--- ");
2662f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					printsiginfo(&si, verbose(tcp));
2663f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					tprintf(" (%s)" PC_FORMAT_STR " ---",
2664f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						strsignal(WSTOPSIG(status)),
2665f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						PC_FORMAT_ARG);
2666f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				} else
2667f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2668f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						strsignal(WSTOPSIG(status)),
2669f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						signame(WSTOPSIG(status)),
2670f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown						PC_FORMAT_ARG);
2671f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				printtrailer();
267234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
267334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (((tcp->flags & TCB_ATTACHED) ||
267434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			     tcp->nclone_threads > 0) &&
267534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				!sigishandled(tcp, WSTOPSIG(status))) {
267634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_GROUP_EXITING
267734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				handle_group_exit(tcp, WSTOPSIG(status));
267834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#else
267934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				detach(tcp, WSTOPSIG(status));
268034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
268134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
268234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
2683f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
268434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				cleanup();
268534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return -1;
268634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
268734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tcp->flags &= ~TCB_SUSPENDED;
268834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
268934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
2690f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* we handled the STATUS, we are permitted to interrupt now. */
2691f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (interrupted)
2692f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			return 0;
2693f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2694f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			/* ptrace() failed in trace_syscall() with ESRCH.
2695f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Likely a result of process disappearing mid-flight.
2696f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * Observed case: exit_group() terminating
2697f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * all processes in thread group. In this case, threads
2698f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * "disappear" in an unpredictable moment without any
2699f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 * notification to strace via wait().
2700f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			 */
2701f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (tcp->flags & TCB_ATTACHED) {
2702f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				if (tcp_last) {
2703f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					/* Do we have dangling line "syscall(param, param"?
2704f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					 * Finish the line then. We cannot
2705f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					 */
2706f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					tcp_last->flags |= TCB_REPRINT;
2707f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					tprintf(" <unfinished ...>");
2708f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown					printtrailer();
2709f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				}
271034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				detach(tcp, 0);
2711f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			} else {
271234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				ptrace(PTRACE_KILL,
271334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					tcp->pid, (char *) 1, SIGTERM);
271434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				droptcb(tcp);
271534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
271634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
271734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
271834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_EXITING) {
271934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef TCB_GROUP_EXITING
272034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp->flags & TCB_GROUP_EXITING) {
272134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				if (handle_group_exit(tcp, 0) < 0)
272234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project					return -1;
272334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				continue;
272434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
272534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
272634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tcp->flags & TCB_ATTACHED)
272734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				detach(tcp, 0);
2728f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
272934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				cleanup();
273034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				return -1;
273134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			}
273234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
273334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
273434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (tcp->flags & TCB_SUSPENDED) {
273534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (!qflag)
273634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				fprintf(stderr, "Process %u suspended\n", pid);
273734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			continue;
273834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
273934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tracing:
2740f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		/* Remember current print column before continuing. */
2741f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		tcp->curcol = curcol;
2742f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
274334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			cleanup();
274434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			return -1;
274534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
274634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
274734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return 0;
274834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
274934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
275034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif /* !USE_PROCFS */
275134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
275234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#include <stdarg.h>
275334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
275434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
275534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projecttprintf(const char *fmt, ...)
275634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
275734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	va_list args;
275834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2759f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	va_start(args, fmt);
276034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (outf) {
276134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		int n = vfprintf(outf, fmt, args);
2762f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (n < 0) {
2763f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (outf != stderr)
2764f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				perror(outfname == NULL
2765f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				       ? "<writing to pipe>" : outfname);
2766f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		} else
276734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			curcol += n;
276834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
276934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	va_end(args);
277034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	return;
277134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
277234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
277334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
277434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectprintleader(tcp)
277534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectstruct tcb *tcp;
277634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
2777f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	if (tcp_last) {
2778f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		if (tcp_last->ptrace_errno) {
2779f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			if (tcp_last->flags & TCB_INSYSCALL) {
2780f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				tprintf(" <unavailable>)");
2781f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown				tabto(acolumn);
2782f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			}
2783f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tprintf("= ? <unavailable>\n");
2784f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tcp_last->ptrace_errno = 0;
2785f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
2786f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tcp_last->flags |= TCB_REPRINT;
2787f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown			tprintf(" <unfinished ...>\n");
2788f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown		}
278934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
279034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	curcol = 0;
279134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if ((followfork == 1 || pflag_seen > 1) && outfname)
279234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tprintf("%-5d ", tcp->pid);
279334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	else if (nprocs > 1 && !outfname)
279434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tprintf("[pid %5u] ", tcp->pid);
279534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (tflag) {
279634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		char str[sizeof("HH:MM:SS")];
279734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		struct timeval tv, dtv;
279834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		static struct timeval otv;
279934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
280034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		gettimeofday(&tv, NULL);
280134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		if (rflag) {
280234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (otv.tv_sec == 0)
280334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				otv = tv;
280434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tv_sub(&dtv, &tv, &otv);
280534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tprintf("%6ld.%06ld ",
280634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				(long) dtv.tv_sec, (long) dtv.tv_usec);
280734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			otv = tv;
280834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
280934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		else if (tflag > 2) {
281034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			tprintf("%ld.%06ld ",
281134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				(long) tv.tv_sec, (long) tv.tv_usec);
281234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
281334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		else {
281434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			time_t local = tv.tv_sec;
281534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			strftime(str, sizeof(str), "%T", localtime(&local));
281634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			if (tflag > 1)
281734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
281834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project			else
281934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project				tprintf("%s ", str);
282034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		}
282134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
282234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (iflag)
282334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		printcall(tcp);
282434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
282534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
282634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
282734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projecttabto(col)
282834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectint col;
282934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
283034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (curcol < col)
283134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		tprintf("%*s", col - curcol, "");
283234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
283334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
283434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Projectvoid
2835f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownprinttrailer(void)
283634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project{
283734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tprintf("\n");
283834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	tcp_last = NULL;
283934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
284034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
284134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#ifdef HAVE_MP_PROCFS
284234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2843f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownint
2844f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownmp_ioctl(int fd, int cmd, void *arg, int size)
2845f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{
284634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	struct iovec iov[2];
284734d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	int n = 1;
284834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
284934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	iov[0].iov_base = &cmd;
285034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	iov[0].iov_len = sizeof cmd;
285134d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	if (arg) {
285234d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		++n;
285334d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		iov[1].iov_base = arg;
285434d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project		iov[1].iov_len = size;
285534d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project	}
285634d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
2857f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown	return writev(fd, iov, n);
285834d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project}
285934d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project
286034d6eabc451f16d5f168fc1595ee604f21bccc51The Android Open Source Project#endif
2861