strace.c revision 328bf250bde8167cec6f2f5bf35463fb4ffb6f9f
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h>
363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
48f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#include <sys/utsname.h>
4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
5144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# if defined __NR_tkill
5244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
5844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) kill((tid), (sig))
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
618470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if defined(IA64)
627b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
6596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
66418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
67418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
6896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
6941c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
70f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
7275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
73e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
74e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
75fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenkostatic int iflag = 0, rflag = 0, tflag = 0;
76fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenkostatic int print_pid_pfx = 0;
77b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
78b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* -I n */
79b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkoenum {
80b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NOT_SET        = 0,
81b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_ANYWHERE       = 1, /* don't block/ignore any signals */
82b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_WHILE_WAIT     = 2, /* block fatal signals while decoding syscall. default */
83b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NEVER          = 3, /* block fatal signals. default if '-o FILE PROG' */
84b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    NUM_INTR_OPTS
86b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko};
87b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkostatic int opt_intr;
88b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* We play with signal mask only if this mode is active: */
89b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#define interactive (opt_intr == INTR_WHILE_WAIT)
90b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
10631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
10731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize (post_attach_sigstop == 0)
10831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
10931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
11031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize 0
11131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
11231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
11317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
11417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
11517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1178a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1188a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1198a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1208a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1218a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
122a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
123a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
12475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
125eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
126b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
127ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
128ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
131102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic int acolumn = DEFAULT_ACOLUMN;
132102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
133b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
134ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
135000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenkostruct tcb *printing_tcp = NULL;
136ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
137ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1382b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
139ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkostatic char *os_release; /* from uname() */
142f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1434c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp);
144e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
151a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#else
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
153a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#endif
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
156cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
159b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkousage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
160b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko              [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
161cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko              [-P path] [PROG [ARGS]]\n\
162b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
163cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko              [PROG [ARGS]]\n\
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
165b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
166b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
168cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-F -- attempt to follow vforks\n\
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
170b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-I interruptible\n\
171b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   1: no signals are blocked\n\
172b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   2: fatal signals are blocked while decoding syscall (default)\n\
173b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   3: fatal signals are always blocked (default if '-o FILE PROG')\n\
174b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   4: fatal signals and SIGTSTP (^Z) are always blocked\n\
175b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko      (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
178cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-T -- print time spent in each syscall\n\
179cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1818a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
182cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-h -- print help message\n\
183cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-V -- print version\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
193de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
194de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
1958a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
196de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
19717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
199de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
20475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
20575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
20675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
20775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
20875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
20975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
21075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
21175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
21275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
21375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
21582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	char *msg;
21682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
21744d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
21882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
21982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We want to print entire message with single fprintf to ensure
22082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * message integrity if stderr is shared with other programs.
22182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * Thus we use vasprintf + single fprintf.
22282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 */
22382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	msg = NULL;
224cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko	if (vasprintf(&msg, fmt, p) >= 0) {
22582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
22682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
22782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
22882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
22982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		free(msg);
23082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	} else {
23182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		/* malloc in vasprintf failed, try it without malloc */
23282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		fprintf(stderr, "%s: ", progname);
23382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		vfprintf(stderr, fmt, p);
23482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
23582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, ": %s\n", strerror(err_no));
23682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
23782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			putc('\n', stderr);
23882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	}
23982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We don't switch stderr to buffered, thus fprintf(stderr)
24082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * always flushes its output and this is not necessary: */
24182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* fflush(stderr); */
24275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
26575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
26675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
26775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
26875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
26975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
27075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
27175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
27275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
27375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
2761d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
2771d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
2781d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
2791d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
2801d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
2811d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
2821d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
2831d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
2841d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
285c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
286c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
287c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
288c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
289c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
290c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
291c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
292c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
29331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
29431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int
29531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid)
29631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
29731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int r;
29831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (!use_seize)
29931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return ptrace(PTRACE_ATTACH, pid, 0, 0);
30031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
30131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (r)
30231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return r;
30331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
30431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	return r;
30531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
30631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
30731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
30831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
30931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
3101f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3131f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
3141f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
3151f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
3161f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
3171f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
3181f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
3191f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
3201f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
3211f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
3221f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3271f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3291f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenkostatic void kill_save_errno(pid_t pid, int sig)
33375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko{
33475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int saved_errno = errno;
33575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
33675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	(void) kill(pid, sig);
33775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	errno = saved_errno;
33875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko}
33975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
3402e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3412e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprintf(const char *fmt, ...)
3422e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3432e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_list args;
3442e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3452e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_start(args, fmt);
3462e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (outf) {
3472e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		int n = vfprintf(outf, fmt, args);
3482e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n < 0) {
3492e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (outf != stderr)
3502e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				perror(outfname == NULL
3512e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				       ? "<writing to pipe>" : outfname);
3522e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		} else
3532e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			curcol += n;
3542e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
3552e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_end(args);
3562e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
3572e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3582e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3592e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprints(const char *str)
3602e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3612e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (outf) {
3622e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		int n = fputs(str, outf);
3632e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n >= 0) {
3642e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			curcol += strlen(str);
3652e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			return;
3662e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
3672e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (outf != stderr)
3682e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			perror(outfname == NULL
3692e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			       ? "<writing to pipe>" : outfname);
3702e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
3712e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
3722e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkoprintleader(struct tcb *tcp)
3752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3762e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (printing_tcp) {
3772e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (printing_tcp->ptrace_errno) {
3782e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (printing_tcp->flags & TCB_INSYSCALL) {
3792e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprints(" <unavailable>) ");
3802e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tabto();
3812e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			}
3822e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints("= ? <unavailable>\n");
3832e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			printing_tcp->ptrace_errno = 0;
3842e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		} else if (!outfname || followfork < 2 || printing_tcp == tcp) {
3852e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			printing_tcp->flags |= TCB_REPRINT;
3862e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints(" <unfinished ...>\n");
3872e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
3882e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
3892e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3902e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	printing_tcp = tcp;
3912e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	curcol = 0;
3922e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3932e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (print_pid_pfx)
3942e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("%-5d ", tcp->pid);
3952e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	else if (nprocs > 1 && !outfname)
3962e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("[pid %5u] ", tcp->pid);
3972e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3982e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (tflag) {
3992e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		char str[sizeof("HH:MM:SS")];
4002e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		struct timeval tv, dtv;
4012e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		static struct timeval otv;
4022e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4032e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		gettimeofday(&tv, NULL);
4042e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (rflag) {
4052e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (otv.tv_sec == 0)
4062e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				otv = tv;
4072e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tv_sub(&dtv, &tv, &otv);
4082e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%6ld.%06ld ",
4092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) dtv.tv_sec, (long) dtv.tv_usec);
4102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			otv = tv;
4112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else if (tflag > 2) {
4132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%ld.%06ld ",
4142e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) tv.tv_sec, (long) tv.tv_usec);
4152e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4162e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else {
4172e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			time_t local = tv.tv_sec;
4182e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			strftime(str, sizeof(str), "%T", localtime(&local));
4192e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (tflag > 1)
4202e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
4212e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			else
4222e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s ", str);
4232e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4242e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
4252e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (iflag)
4262e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		printcall(tcp);
4272e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4282e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4292e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
4302e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotabto(void)
4312e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
4322e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (curcol < acolumn)
4332e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprints(acolumn_spaces + curcol);
4342e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4352e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
43610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
43710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
43810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
43910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
44010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
44110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
44210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
44310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
44410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4457b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
446cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
44710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
44810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
44910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4504bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
4514bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
4524bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
4534bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
4544bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
4554bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
45610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
4573d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
45810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
45910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
46010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
46110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
4623d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
4633d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
4643d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
46510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
4663d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
46710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
46810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
46910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4707dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
47110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
47210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
47310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
47410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
47510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
47610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
47710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
47810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
47910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
48010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
48110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
48210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
48310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
4847dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
4857dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
48610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
48710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
48810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
4897dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
49010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4917dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
49210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4937dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
4947dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
4957dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
49610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4977dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
49810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
49910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
5007dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
5017dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
5027dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
5037dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
50410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
50510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
5067dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
50710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
5087dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
5097dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
5107dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
5117dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
5127dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
5137dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
5141d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
5157dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
51610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
51710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5183d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
51910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
52010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
52110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
5227a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
5237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
5243d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
52510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
52610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
52710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
528558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkostatic void
529558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkoprocess_opt_p_list(char *opt)
530e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko{
531e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	while (*opt) {
532e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		/*
533e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
534e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * pidof uses space as delim, pgrep uses newline. :(
535e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 */
536e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		int pid;
537e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char *delim = opt + strcspn(opt, ", \n\t");
538e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char c = *delim;
539e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
540e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = '\0';
541e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		pid = atoi(opt); /* TODO: stricter parsing of the number? */
542e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid <= 0) {
543e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			error_msg("Invalid process id: '%s'", opt);
544e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			*delim = c;
545e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			return;
546e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
547e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid == strace_tracer_pid) {
548e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			error_msg("I'm sorry, I can't let you do that, Dave.");
549e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			*delim = c;
550e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			return;
551e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
552e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = c;
55375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		alloc_tcb(pid, 0);
554e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (c == '\0')
555e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			break;
556e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		opt = delim + 1;
557e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	}
558e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko}
559e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
5692e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
570b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
575ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
576ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
577ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
578014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
579ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
580ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
581ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
58275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
58375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
58475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
585ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
586ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
587ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
588ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
589ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
59075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
59175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
59275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
593ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
594ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
59744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
59875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (!(tcp->flags & TCB_INUSE))
59975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue;
60075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
601d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
60275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (tcp->flags & TCB_ATTACHED)
60375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue; /* no, we already attached it */
604d116a7338645af45090aecc331701e999148d284Denys Vlasenko
605d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Reinitialize the output since it may have changed */
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
6073d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
609ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
6107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
618381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
620381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
621381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
622381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
6237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
62931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (ptrace_attach_or_seize(tid) < 0) {
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
631f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
632f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
633381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
634f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
635381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (debug)
636381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
637381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
638381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
639381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
64031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
643381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
644381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
645381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
646381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
647381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
648381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
6497a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
6507a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
6567a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
6577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
6587a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
65944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
66175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				if (!(tcp->flags & TCB_ATTACHED)) {
662f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
663f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
664f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
665f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
666f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
667f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
6697a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
6707a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
67131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace_attach_or_seize(tcp->pid) < 0) {
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
67675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
677f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko		if (debug)
678f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
686ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
69002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
692f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
69302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
69444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
69502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
69602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
69702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
69802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
69902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
7001201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
70102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
70202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
70502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
70602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
70802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
70902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
71002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
71102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
712cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
71302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
71402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
71502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
71602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
71702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
71802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
71902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
72002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
72102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
72202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
72302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
72402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
72502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
72630145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
72702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
72802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
72902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
7304f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			const char *colon = strchr(path, ':');
7314f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (colon) {
7324f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				n = colon - path;
73302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
73402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
73502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
73602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
73702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
73802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
73902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
74002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
74102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
74202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
74302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
74402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
74502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
74602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
74702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
74802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
74902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
75002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
75102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
75202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
75302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
75402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
75502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
75602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
75702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
75802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
75902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
76002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
761cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
76202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
763a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
764ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
765cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
766ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
76775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
76875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
769ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
770ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
7712e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		if (outf != stderr)
7722e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			close(fileno(outf));
77331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!daemonized_tracer && !use_seize) {
77431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
775cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
776ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
77702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
77802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
779ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
78002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
78102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
78202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
78302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
78402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
78502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
78602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
78702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
78802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
78902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
79002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
791ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
792ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
793ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
794ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
795ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
796ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
797ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
798ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
79902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
80002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
801ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
80202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
80302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
804ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
805ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
8062e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
807ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
8082e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
8092e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
8102e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
811ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
812c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
8132e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
814ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
815ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
816ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
817ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
818ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
819ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
820ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
821ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
822ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
823ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
824ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
825ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
826ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
827ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
828ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
829ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
830ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
83102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
83202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
833cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
83402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
835ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
8362e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
83775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
8382e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
83931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!use_seize) {
84031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* child did PTRACE_TRACEME, nothing to do in parent */
84131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		} else {
84231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked) {
84331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* Wait until child stopped itself */
84431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				int status;
84531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				while (waitpid(pid, &status, WSTOPPED) < 0) {
84631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (errno == EINTR)
84731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko						continue;
84831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("waitpid");
84931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
85031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
85175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko					kill_save_errno(pid, SIGKILL);
85231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("Unexpected wait status %x", status);
85331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
85431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
85531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Else: vforked case, we have no way to sync.
85631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * Just attach to it as soon as possible.
85731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * This means that we may miss a few first syscalls...
85831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
85931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
86031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace_attach_or_seize(pid)) {
86175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				kill_save_errno(pid, SIGKILL);
86231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				perror_msg_and_die("Can't attach to %d", pid);
86331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
86431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked)
86531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGCONT);
86631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
8672e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
868f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
86975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
870f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
87175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
8722e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
8732e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
8742e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
8752e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
8762e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
8772e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
878f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		alloctcb(pid);
879f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		/* attaching will be done later, by startup_attach */
880ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
88102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
88202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
883b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
884b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
885b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
886b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
887b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
88804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
8893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
890b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
8912fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
8922fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
8932fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
8942fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
895b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
8965d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
8975d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
89804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
8995d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
90004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
90131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
90204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
90304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
9044c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko		kill_save_errno(pid, SIGSTOP);
90504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
90604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
90704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
908b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
909b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
910b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
911b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
912b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
91304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
914b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
91504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
916b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
917b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
9184c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			if (errno == ECHILD)
919b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
92004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
92104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
92204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
92304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
92404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
92504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
92604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
92704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
92804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
92904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
93004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
93104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
93204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
93304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
93404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
93504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
93604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
93704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
93804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
93904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
94004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
94104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
9424c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			kill_save_errno(pid, SIGKILL);
94304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
94404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
945b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
946b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
9472fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
94804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
94904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
95004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
95104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
95204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
95304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
954b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
95504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
95604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
95704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
95804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
95904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
96004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
96104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
96204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
96304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
9642fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
96504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
96604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
96704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
968b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
96904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
97004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
97104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
97204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
97304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
974b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
975b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
97604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
977f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
97804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (debug)
97904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
98004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
98104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
98204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
98304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
98404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
985b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
9863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
9883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
9893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
9903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
9913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
9923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
9933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
9943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
9953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
9963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
9973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
9983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
9993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
10003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
10013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
10023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
10033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
100404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
100504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
10063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
10073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
10083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
10103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
101175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
10123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
10143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
10153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
101675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
101704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
101804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
10193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
10203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
10213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
10243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
10253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
10273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
10283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
10293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
10303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
103104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
103204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
103304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
103475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
103575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
103675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
103775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
103804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
103904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
104004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
104104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
104204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
104304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
10443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
10463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
104704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
104804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
10493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
10513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
10523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
10533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
10543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
10553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
10563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
105704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
105804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
105904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
10603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
10623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
10633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
106504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
106675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
10673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
107175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
1072f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
10733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
1074f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1075f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
10763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
10773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
107904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
108004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
10813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
108231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
108331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# ifdef USE_SEIZE
108431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void
108531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void)
108631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
108731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int pid;
108831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
108931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	pid = fork();
109031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid < 0)
109131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		perror_msg_and_die("fork");
109231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
109331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid == 0) {
109431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		pause();
109531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		_exit(0);
109631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
109731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
109831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	/* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap.  After
109931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * attaching tracee continues to run unless a trap condition occurs.
110031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * PTRACE_SEIZE doesn't affect signal or group stop state.
110131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 */
110231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
110331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
110431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	} else if (debug) {
110531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
110631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
110731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
110831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	kill(pid, SIGKILL);
110931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
111031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	while (1) {
111131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int status, tracee_pid;
111231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
111331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		errno = 0;
111431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tracee_pid = waitpid(pid, &status, 0);
111531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (tracee_pid <= 0) {
111631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (errno == EINTR)
111731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
111831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d",
111931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					 __func__, tracee_pid);
112031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
112131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (WIFSIGNALED(status)) {
112231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			return;
112331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
112431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		error_msg_and_die("%s: unexpected wait status %x",
112531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				__func__, status);
112631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
112731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
112831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# else /* !USE_SEIZE */
112931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#  define test_ptrace_seize() ((void)0)
113031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# endif
113131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
1132ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void
1133f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void)
1134f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{
1135f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	struct utsname u;
1136f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (uname(&u) < 0)
1137f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		perror_msg_and_die("uname");
1138f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	os_release = strdup(u.release);
1139f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (!os_release)
1140f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		die_out_of_memory();
1141f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko}
1142f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1143ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko/*
1144ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Initialization part of main() was eating much stack (~0.5k),
1145ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * which was unused after init.
1146ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * We can reuse it if we move init code into a separate function.
1147ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko *
1148ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Don't want main() to inline us and defeat the reason
1149ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * we have a separate function.
1150ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko */
1151ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void __attribute__ ((noinline))
1152ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoinit(int argc, char *argv[])
115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
1155e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	int c;
115606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
115908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
116008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
116175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
116275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
1163f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	get_os_release();
1164f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1165ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
1166ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
11674f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
11681d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
11691d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
11704f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
11711d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
11721d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
11734f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
11744f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
1175ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
1177138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
1178138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
11848a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
1185ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1186b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1189e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1190cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1191e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1192e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1193e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1194e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1195e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1196cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1197e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1198e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1203ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1204ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1205ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
120641c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
120706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
120806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
12348a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
12358a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
12368a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
12419c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
124417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
124517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
124617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
1249102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1250102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				error_msg_and_die("Bad column width '%s'", optarg);
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1262e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			process_opt_p_list(optarg);
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
12648a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
12658a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
12668a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1267cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
12688a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
12698a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1272dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1273b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1274dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1282de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
12831d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
12841d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1285de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
1286b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		case 'I':
1287b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = atoi(optarg);
1288b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1289b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1290b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			}
1291b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			break;
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1297837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1298837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1300102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1301102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
13021d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1303102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1304102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1305102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1306837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1307fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (!argv[0] == !nprocs)
1308ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1309ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1310fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 && daemonized_tracer) {
1311cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1312d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1313d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
131406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
131506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
131606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1317cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1318cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1319cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1320cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1326cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
13285d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
13295d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1330cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
134104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
13423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
134331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	test_ptrace_seize();
13448044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
134737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
134837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
134937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
135037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
135137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
135237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
13537dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
13547dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
13557dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
135654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
13573d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
13583d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
1359328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko	} else {
1360328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		/* -ff without -o FILE is the same as single -f */
1361328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		if (followfork > 1)
1362328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko			followfork = 1;
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1365cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1366a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1367a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1368a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1370cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1371837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
1372b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (!opt_intr)
1373b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = INTR_NEVER;
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1375369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1376b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (!opt_intr)
1377b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		opt_intr = INTR_WHILE_WAIT;
1378b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
1379b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	/* argv[0]	-pPID	-oFILE	Default interactive setting
1380b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	0	INTR_WHILE_WAIT
1381b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	0	INTR_WHILE_WAIT
1382b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	1	INTR_NEVER
1383b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	1	INTR_WHILE_WAIT
138454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
138554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
138654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
138754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
138854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
138954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
1390837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (argv[0])
1391837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
1398b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1399b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1400b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (opt_intr != INTR_ANYWHERE) {
1401b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_BLOCK_TSTP_TOO)
1402b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1403b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/*
1404b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1405b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * fatal signals are blocked while syscall stop is processed,
1406b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * and acted on in between, when waiting for new syscall stops.
1407b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In non-interactive mode, signals are ignored.
1408b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 */
1409b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_WHILE_WAIT) {
1410b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGHUP);
1411b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGINT);
1412b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGQUIT);
1413b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGPIPE);
1414b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGTERM);
1415b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_handler = interrupt;
1416b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		}
1417b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/* SIG_IGN, or set handler for these */
1418b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGHUP, &sa, NULL);
1419b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGINT, &sa, NULL);
1420b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGQUIT, &sa, NULL);
1421b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGPIPE, &sa, NULL);
1422b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGTERM, &sa, NULL);
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1424553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1425553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1426553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1427553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1428553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1429553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1430553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1432fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 || daemonized_tracer)
143302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
143402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1435fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	/* Do we want pids printed in our -o OUTFILE?
1436fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -ff: no (every pid has its own file); or
1437fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -f: yes (there can be more pids in the future); or
1438fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -p PID1,PID2: yes (there are already more than one pid)
1439fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 */
1440fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14432b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1444418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
14457b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
14467b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
14477b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
14487b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
14497b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
14507b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
145118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
145218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
145318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
14541d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!newtab || !newtcbs)
14551d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
14567b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
14577b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
145818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
145918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
14607b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
14617b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
146310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1468418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1469418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1470418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1471ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1472ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
147418da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1476381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko			tcp->flags = TCB_INUSE;
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1478a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#if SUPPORTED_PERSONALITIES > 1
1479a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin			tcp->currpers = current_personality;
1480a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#endif
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
14821d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (debug)
14831d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
148410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
148510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1492eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
149354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
149654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
149754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
149854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1500ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
150154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
150254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
150554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15101201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
151419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
15161d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko	if (debug)
15171d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1518eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1519822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1521eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
152219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15250a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
152675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * Never call DETACH twice on the same process as both unattached and
152775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * attached-unstopped processes give the same ESRCH.  For unattached process we
152875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * would SIGSTOP it and wait for its SIGSTOP notification forever.
152975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko */
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
15314c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkodetach(struct tcb *tcp)
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
153375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int error;
153475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int status, sigstop_expected;
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1537840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
15417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
15427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
15447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
15457bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
15467bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
15477bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
154875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
154975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	sigstop_expected = 0;
155075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (tcp->flags & TCB_ATTACHED) {
155175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		/*
155275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * We attached but possibly didn't see the expected SIGSTOP.
155375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * We must catch exactly one as otherwise the detached process
155475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * would be left stopped (process state T).
155575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 */
155675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
155775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
155875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (error == 0) {
155975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			/* On a clear day, you can see forever. */
156075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
156175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (errno != ESRCH) {
156275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			/* Shouldn't happen. */
156375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			perror("detach: ptrace(PTRACE_DETACH, ...)");
156475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
156575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (my_tkill(tcp->pid, 0) < 0) {
156675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			if (errno != ESRCH)
156775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				perror("detach: checking sanity");
156875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
156975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
157075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			if (errno != ESRCH)
157175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				perror("detach: stopping child");
157275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
157375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else
157475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			sigstop_expected = 1;
15757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
157675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
157775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (sigstop_expected) {
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
15797508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
158037ab4b79de57c1657e41f96a96fa699a08194a80Denys Vlasenko			if (waitpid(tcp->pid, &status, __WALL) < 0) {
15817508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
15827508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15837508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
15857508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15867508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
15877508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
15887508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
15897508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
15907508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
15917508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
15927508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
15937508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
15947508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
15957508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
159637ab4b79de57c1657e41f96a96fa699a08194a80Denys Vlasenko					if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16017508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16027508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16037508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16057508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
16114c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, 0);
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1614732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
161575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1616732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1617732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1620ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (!qflag && (tcp->flags & TCB_ATTACHED))
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1626a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16311201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
16353521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	int fatal_sig;
16363521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko
16373521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	/* 'interrupted' is a volatile object, fetch it only once */
16383521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	fatal_sig = interrupted;
16393521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	if (!fatal_sig)
16403521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko		fatal_sig = SIGTERM;
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1642ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1643ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
1649000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko		if (printing_tcp &&
1650000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko		    (!outfname || followfork < 2 || printing_tcp == tcp)) {
1651000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			tprints(" <unfinished ...>\n");
1652000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			printing_tcp = NULL;
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
165475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (!(tcp->flags & TCB_STRACE_CHILD))
16554c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko			detach(tcp);
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
1658a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko			kill(tcp->pid, fatal_sig);
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16661201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
1668a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko	interrupted = sig;
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16736d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
16766d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
16791201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16811945ccc3fbd5b56008c4a6b0cdd4611616201675Denys Vlasenko	static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168335aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
168435aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
168735aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16948f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
16956d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
16978f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
16988f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
16998f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
17021201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17041945ccc3fbd5b56008c4a6b0cdd4611616201675Denys Vlasenko	static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
17201201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
172326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
172426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
1725eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
172626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1728eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
1729f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int pid;
1730f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int wait_errno;
1731f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int status, sig;
173231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int stopped;
1733f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		struct tcb *tcp;
1734f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		unsigned event;
1735f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1736222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
1737eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
1738eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1739eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
174026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
174126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
17425bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
17432f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
17442f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
174526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
17462f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
17475bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
17482f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
174926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
175026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
1751cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
17522f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
17532f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
175426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
175526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
175626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
1758eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1759eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
1762eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
1763eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1765eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
1772eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
1773eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
1774eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
17754c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("wait");
1776eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
177910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
178010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
17817dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
178210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
178310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
1784f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1785f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		event = ((unsigned)status >> 16);
17861d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		if (debug) {
17871d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
1788f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			if (event != 0) {
17891d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				static const char *const event_names[] = {
17901d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
17911d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
17921d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
17931d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
17941d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
17951d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
17961d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				};
17971d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				const char *e;
1798f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (event < ARRAY_SIZE(event_names))
1799f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					e = event_names[event];
18001d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				else {
1801f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					sprintf(buf, "?? (%u)", event);
18021d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = buf;
18031d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				}
18041d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, " PTRACE_EVENT_%s", e);
18051d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			}
18061d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
18071d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
18081d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
18091d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
18101d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
18111d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18121d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
18131d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
18141d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18151d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
18161d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
18171d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
18181d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
18191d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
18205bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
18211d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
18221d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
18235bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
18241d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
18251d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1827f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Look up 'pid' in our table. */
18285d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
1829f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1830f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Under Linux, execve changes pid to thread leader's pid,
1831f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and we see this changed pid on EVENT_EXEC and later,
1832f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * execve sysexit. Leader "disappears" without exit
1833f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * notification. Let user know that, drop leader's tcb,
1834f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and fix up pid in execve thread's tcb.
1835f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * Effectively, execve thread's tcb replaces leader's tcb.
1836f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1837f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1838f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * on exit syscall) in multithreaded programs exactly
1839f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * in order to handle this case.
1840f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1841f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1842f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * On 2.6 and earlier, it can return garbage.
1843f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 */
1844f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1845f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			long old_pid = 0;
1846f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1847f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid > 0
1848f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid != pid
1849f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			) {
1850f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				struct tcb *execve_thread = pid2tcb(old_pid);
1851f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
1852f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					outf = tcp->outf;
1853f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					curcol = tcp->curcol;
1854f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					if (!cflag) {
1855000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko						if (printing_tcp)
1856f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko							tprints(" <unfinished ...>\n");
1857f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						printleader(tcp);
1858000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko						tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1859000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko						printing_tcp = NULL;
1860f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						fflush(outf);
1861f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					}
1862f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					if (execve_thread) {
1863f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						/* swap output FILEs (needed for -ff) */
1864f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						tcp->outf = execve_thread->outf;
1865f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						execve_thread->outf = outf;
1866f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					}
1867f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					droptcb(tcp);
1868f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
1869f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				tcp = execve_thread;
1870f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
1871f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->pid = pid;
1872f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->flags |= TCB_REPRINT;
1873f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
1874f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			}
1875f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		}
1876f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
18775d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
187841c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
1879e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
1880e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
1881e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
1882e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
1883e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
1884e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
1885e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
1886e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
1887e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
1888418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
188931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
1890e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
1891833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
1892e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
18938b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
1894e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
1895e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
1896e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
1897e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
1898e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
189997c503fa2e9cd02126feae659f133631c8eb36f1Denys Vlasenko					ptrace(PTRACE_CONT, pid, (char *) 0, 0);
1900cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
1901e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1903eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
1904eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
1905ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
190613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1910eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
1912a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
1913a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
1914e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
191713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
1918000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s %s+++\n",
19192efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
192013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
192113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
1922000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s +++\n",
192313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
19242efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
1925000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
19275e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko			fflush(tcp->outf);
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
1932a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
1933a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
1934000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			if (tcp == printing_tcp) {
1935000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprints(" <unfinished ...>\n");
1936000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
19370a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
193819cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
193919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
1940000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1941000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
194219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
19435e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko			fflush(tcp->outf);
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1953f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
1954f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
1955f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
1956f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
195802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
196002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
19612ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
19636cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
19646cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
197044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
197144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (debug)
197244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
197344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
197444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
197544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
197644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
19773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
19783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
19793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
1980f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
1981f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
198231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		sig = WSTOPSIG(status);
198331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
1984f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event != 0) {
198531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Ptrace event */
198631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
198731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
19886703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				/*
19896703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop or group-stop.
19906703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
19916703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 */
199231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (sig == SIGSTOP
199331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTSTP
199431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTIN
199531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTOU
199631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				) {
199731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					stopped = 1;
199831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					goto show_stopsig;
199931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
200031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
200131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
2002f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2003f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2004f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2005f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2006f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2007f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2008f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2009f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2010f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2011f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2012f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2013f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2014f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
20156cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20186cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
201931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			siginfo_t si;
202031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
202131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Nonzero (true) if tracee is stopped by signal
202231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * (as opposed to "tracee received signal").
202331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
202431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
20256703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#ifdef USE_SEIZE
202631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig:
20276703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif
2028e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
20296cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2030c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
20316b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
20326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
20337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2034932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2035932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
20367b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
20376b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
20387b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
20396b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
20402ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
20416b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
20422ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
20432ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
20447b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
204631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!stopped) {
204760fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("--- ");
20486b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
2049000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprintf(" (%s)" PC_FORMAT_STR " ---\n",
20506cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig)
20516b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
20526b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
2053000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
20546cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig),
20556cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
20566b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2057000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
20585e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko				fflush(tcp->outf);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
206131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!stopped)
206231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* It's signal-delivery-stop. Inject the signal */
206331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				goto restart_tracee;
206431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
206531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* It's group-stop */
206631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
206731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (use_seize) {
206831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/*
206931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This ends ptrace-stop, but does *not* end group-stop.
207031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This makes stopping signals work properly on straced process
207131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * (that is, process really stops. It used to continue to run).
207231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 */
207331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
207431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cleanup();
207531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					return -1;
207631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
207731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
207831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
207931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* We don't have PTRACE_LISTEN support... */
208031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
20816cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20832ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
20842ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
208502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
208602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
20872ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
20882ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
20892ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
20902ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
20912ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2092eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2093eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2094eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2095eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2096f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
2097ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2098f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			if (printing_tcp) {
2099f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko				/* Do we have dangling line "syscall(param, param"?
2100f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko				 * Finish the line then.
2101f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 */
2102f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko				printing_tcp->flags |= TCB_REPRINT;
2103f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko				tprints(" <unfinished ...>\n");
2104f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko				printing_tcp = NULL;
2105f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko				fflush(tcp->outf);
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2107f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			/* We assume that ptrace error was caused by process death.
2108f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * We used to detach(tcp) here, but since we no longer
2109f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * implement "detach before death" policy/hack,
2110f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * we can let this process to report its death to us
2111f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * normally, via WIFEXITED or WIFSIGNALED wait status.
2112f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 */
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21156cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
21166cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
21176cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2118ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2119ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
21206cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
2127ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2128ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoint
2129ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkomain(int argc, char *argv[])
2130ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko{
2131ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	init(argc, argv);
2132ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2133ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	/* Run main tracing loop */
2134ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (trace() < 0)
2135ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		return 1;
2136ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2137ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	cleanup();
2138ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	fflush(NULL);
2139ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (exit_code > 0xff) {
2140ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Avoid potential core file clobbering.  */
2141ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		struct rlimit rlim = {0, 0};
2142ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		setrlimit(RLIMIT_CORE, &rlim);
2143ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2144ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Child was killed by a signal, mimic that.  */
2145ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code &= 0xff;
2146ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		signal(exit_code, SIG_DFL);
2147ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		raise(exit_code);
2148ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Paranoia - what if this signal is not fatal?
2149ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		   Exit with 128 + signo then.  */
2150ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code += 128;
2151ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	}
2152ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2153ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	return exit_code;
2154ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko}
2155