strace.c revision 6e0bfd11ac1aa36713d9a65542ae86dd607ae374
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
353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
44f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#include <sys/utsname.h>
458470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if defined(IA64)
467b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
477b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
48a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko/* In some libc, these aren't declared. Do it ourself: */
4996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
50418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
51418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
5296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
53a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
54a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#if defined __NR_tkill
55a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
56a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#else
57a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko   /* kill() may choose arbitrarily the target task of the process group
58a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko      while we later wait on a that specific TID.  PID process waits become
59a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko      TID task specific waits for a process under ptrace(2).  */
60a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) kill((tid), (sig))
62a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#endif
63a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
64a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#undef KERNEL_VERSION
65a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
66a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
67a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkocflag_t cflag = CFLAG_NONE;
68a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int followfork = 0;
69f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
70a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int xflag = 0;
71a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool debug_flag = 0;
72a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool Tflag = 0;
73a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool qflag = 0;
743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
7575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
76a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic unsigned int tflag = 0;
77a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool iflag = 0;
78a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool rflag = 0;
79a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool print_pid_pfx = 0;
80b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
81b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* -I n */
82b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkoenum {
83b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NOT_SET        = 0,
84b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_ANYWHERE       = 1, /* don't block/ignore any signals */
85b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_WHILE_WAIT     = 2, /* block fatal signals while decoding syscall. default */
86b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NEVER          = 3, /* block fatal signals. default if '-o FILE PROG' */
87b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
88b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    NUM_INTR_OPTS
89b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko};
90b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkostatic int opt_intr;
91b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* We play with signal mask only if this mode is active: */
92b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#define interactive (opt_intr == INTR_WHILE_WAIT)
93b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
104ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
106ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
10931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
11031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize (post_attach_sigstop == 0)
11131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
11231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
11331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize 0
11431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
11531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
11617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
117a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool not_failing_only = 0;
11817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1198a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
120a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool show_fd_path = 0;
1218a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1228a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
123a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool tracing_paths = 0;
1248a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
12561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool detach_on_execve = 0;
12661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool skip_startup_execve = 0;
12761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
128a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
129a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
13075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
131eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
132b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
133ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
134ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int max_strlen = DEFAULT_STRLEN;
137a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic unsigned int acolumn = DEFAULT_ACOLUMN;
138102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
139b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
140ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
141000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenkostruct tcb *printing_tcp = NULL;
142a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic unsigned int curcol;
143ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1442b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
145ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1476e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned os_release; /* generated from uname()'s u.release */
148f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1494c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp);
150e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
151e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
152e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
157a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#else
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
159a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#endif
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
162cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
165b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkousage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
166b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko              [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
167cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko              [-P path] [PROG [ARGS]]\n\
168b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
169cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko              [PROG [ARGS]]\n\
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
171b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
1723e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-d -- enable debug output to stderr\n\
173b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
1753e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-F -- attempt to follow vforks (deprecated, use -f)\n\
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
177b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-I interruptible\n\
178b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   1: no signals are blocked\n\
179b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   2: fatal signals are blocked while decoding syscall (default)\n\
180b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   3: fatal signals are always blocked (default if '-o FILE PROG')\n\
181b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   4: fatal signals and SIGTSTP (^Z) are always blocked\n\
182b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko      (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
185cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-T -- print time spent in each syscall\n\
186cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1888a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
189cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-h -- print help message\n\
190cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-V -- print version\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
200de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2028a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
20361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko"
20461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* this is broken, so don't document it
20517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
20661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */
20761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* experimental, don't document it yet (option letter may change in the future!)
20861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko-b -- detach on successful execve\n\
20961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */
210de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
21575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
21675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
21775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
22682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	char *msg;
22782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
22844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
22982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
23082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We want to print entire message with single fprintf to ensure
23182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * message integrity if stderr is shared with other programs.
23282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * Thus we use vasprintf + single fprintf.
23382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 */
23482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	msg = NULL;
235cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko	if (vasprintf(&msg, fmt, p) >= 0) {
23682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
23782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
23882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
23982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
24082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		free(msg);
24182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	} else {
24282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		/* malloc in vasprintf failed, try it without malloc */
24382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		fprintf(stderr, "%s: ", progname);
24482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		vfprintf(stderr, fmt, p);
24582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
24682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, ": %s\n", strerror(err_no));
24782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
24882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			putc('\n', stderr);
24982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	}
25082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We don't switch stderr to buffered, thus fprintf(stderr)
25182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * always flushes its output and this is not necessary: */
25282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* fflush(stderr); */
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
26875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
26975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
27075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
27175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
27275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
27375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
27475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
27575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
27675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
27775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
27875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
27975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
28075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
28175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
28275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
28375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
28475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
2871d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
2881d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
2891d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
2901d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
2911d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
2921d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
2931d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
2941d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
2951d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
296c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
297c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
298c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
299c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
300c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
301c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
302c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
303c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
30431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
30531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int
30631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid)
30731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
30831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int r;
30931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (!use_seize)
31031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return ptrace(PTRACE_ATTACH, pid, 0, 0);
31131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
31231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (r)
31331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return r;
31431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
31531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	return r;
31631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
31731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
31831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
31931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
32031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
3211f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3241f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
3251f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
3261f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
3271f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
3281f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
3291f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
3301f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
3311f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
3321f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
3331f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3381f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3401f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenkostatic void kill_save_errno(pid_t pid, int sig)
34475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko{
34575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int saved_errno = errno;
34675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
34775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	(void) kill(pid, sig);
34875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	errno = saved_errno;
34975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko}
35075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
3512e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3522e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprintf(const char *fmt, ...)
3532e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3542e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_list args;
3552e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3562e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_start(args, fmt);
3572e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (outf) {
3582e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		int n = vfprintf(outf, fmt, args);
3592e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n < 0) {
3602e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (outf != stderr)
3612e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				perror(outfname == NULL
3622e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				       ? "<writing to pipe>" : outfname);
3632e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		} else
3642e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			curcol += n;
3652e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
3662e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_end(args);
3672e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
3682e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3692e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3702e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprints(const char *str)
3712e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3722e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (outf) {
3732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		int n = fputs(str, outf);
3742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n >= 0) {
3752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			curcol += strlen(str);
3762e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			return;
3772e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
3782e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (outf != stderr)
3792e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			perror(outfname == NULL
3802e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			       ? "<writing to pipe>" : outfname);
3812e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
3822e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
3832e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3842e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3857de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkoline_ended(void)
3867de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko{
3877de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	curcol = 0;
3887de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	fflush(outf);
3897de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (!printing_tcp)
3907de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		return;
3917de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	printing_tcp->curcol = 0;
3927de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	printing_tcp = NULL;
3937de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko}
3947de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
3957de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkovoid
3962e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkoprintleader(struct tcb *tcp)
3972e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3987de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	/* If -ff, "previous tcb we printed" is always the same as current,
3997de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	 * because we have per-tcb output files.
4007de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	 */
4017de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (followfork >= 2)
4027de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		printing_tcp = tcp;
4037de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
4042e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (printing_tcp) {
4057de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		outf = printing_tcp->outf;
4067de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		curcol = printing_tcp->curcol;
4072e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (printing_tcp->ptrace_errno) {
4082e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (printing_tcp->flags & TCB_INSYSCALL) {
4092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprints(" <unavailable>) ");
4102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tabto();
4112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			}
4122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints("= ? <unavailable>\n");
4132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			printing_tcp->ptrace_errno = 0;
4147de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->curcol = 0;
4157de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		}
4167de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
4177de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			/*
4187de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * case 1: we have a shared log (i.e. not -ff), and last line
4197de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * wasn't finished (same or different tcb, doesn't matter).
4207de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * case 2: split log, we are the same tcb, but our last line
4217de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
4227de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 */
4232e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints(" <unfinished ...>\n");
4247de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->flags |= TCB_REPRINT;
4257de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->curcol = 0;
4262e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4272e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
4282e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4292e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	printing_tcp = tcp;
4307de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	outf = tcp->outf;
4312e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	curcol = 0;
4322e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4332e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (print_pid_pfx)
4342e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("%-5d ", tcp->pid);
4352e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	else if (nprocs > 1 && !outfname)
4362e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("[pid %5u] ", tcp->pid);
4372e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4382e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (tflag) {
4392e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		char str[sizeof("HH:MM:SS")];
4402e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		struct timeval tv, dtv;
4412e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		static struct timeval otv;
4422e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4432e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		gettimeofday(&tv, NULL);
4442e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (rflag) {
4452e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (otv.tv_sec == 0)
4462e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				otv = tv;
4472e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tv_sub(&dtv, &tv, &otv);
4482e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%6ld.%06ld ",
4492e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) dtv.tv_sec, (long) dtv.tv_usec);
4502e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			otv = tv;
4512e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4522e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else if (tflag > 2) {
4532e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%ld.%06ld ",
4542e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) tv.tv_sec, (long) tv.tv_usec);
4552e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4562e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else {
4572e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			time_t local = tv.tv_sec;
4582e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			strftime(str, sizeof(str), "%T", localtime(&local));
4592e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (tflag > 1)
4602e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
4612e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			else
4622e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s ", str);
4632e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4642e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
4652e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (iflag)
4662e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		printcall(tcp);
4672e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4682e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4692e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
4702e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotabto(void)
4712e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
4722e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (curcol < acolumn)
4732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprints(acolumn_spaces + curcol);
4742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
47610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
47710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
47810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
47910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
48010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
48110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
48210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
48310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
48410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4857b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
486cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
48710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
48810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
48910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4904bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
4914bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
4924bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
4934bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
4944bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
4954bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
49610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
4973d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
49810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
49910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
50010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
50110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
5023d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
5033d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
5043d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
50510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
5063d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
50710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
50810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
50910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5107dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
51110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
51210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
51310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
51410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
51510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
51610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
51710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
51810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
51910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
52010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
52110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
52210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
52310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
5247dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
5257dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
52610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
52710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
52810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
5297dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
53010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5317dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
53210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5337dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
5347dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
5357dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
53610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5377dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
53810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
53910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
5407dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
5417dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
5427dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
5437dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
54410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
54510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
5467dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
54710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
5487dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
5497dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
5507dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
5517dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
5527dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
5537dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
5541d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
5557dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
55610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
55710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5583d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
55910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
56010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
5617de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (outfname && followfork >= 2) {
5627a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
5637a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
5643d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
56510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
56610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
56710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
568558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkostatic void
569558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkoprocess_opt_p_list(char *opt)
570e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko{
571e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	while (*opt) {
572e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		/*
573e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
574e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * pidof uses space as delim, pgrep uses newline. :(
575e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 */
576e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		int pid;
577e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char *delim = opt + strcspn(opt, ", \n\t");
578e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char c = *delim;
579e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
580e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = '\0';
581e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		pid = atoi(opt); /* TODO: stricter parsing of the number? */
582e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid <= 0) {
583e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			error_msg("Invalid process id: '%s'", opt);
584e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			*delim = c;
585e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			return;
586e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
587e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid == strace_tracer_pid) {
588e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			error_msg("I'm sorry, I can't let you do that, Dave.");
589e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			*delim = c;
590e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			return;
591e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
592e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = c;
59375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		alloc_tcb(pid, 0);
594e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (c == '\0')
595e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			break;
596e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		opt = delim + 1;
597e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	}
598e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko}
599e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
6092e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
610b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
615ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
616ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
617ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
618014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
619ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
620ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
621ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
62275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
62375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
62475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
625ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
626ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
627ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
628ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
629ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
63075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
63175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
63275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
633ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
634ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
63744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
63875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (!(tcp->flags & TCB_INUSE))
63975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue;
64075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
641d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
64275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (tcp->flags & TCB_ATTACHED)
64375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue; /* no, we already attached it */
644d116a7338645af45090aecc331701e999148d284Denys Vlasenko
645d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Reinitialize the output since it may have changed */
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
6473d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
64802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
6507a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
658381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
660381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
661381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
662381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
6637a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
66931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (ptrace_attach_or_seize(tid) < 0) {
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
671a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko						if (debug_flag)
672f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
673381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
674f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
675a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko					if (debug_flag)
676381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
677381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
678381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
679381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
68031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
68202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
683381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
684381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
685381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
686381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
687381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
688381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
6897a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
6907a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
69202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
69302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
69402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
69502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
6967a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
6977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
6987a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
69944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
70002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
70175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				if (!(tcp->flags & TCB_ATTACHED)) {
702f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
703f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
704f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
705f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
706f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
707f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
70802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
7097a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
7107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
71131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace_attach_or_seize(tcp->pid) < 0) {
71202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
71302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
71402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
71502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
71675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
717a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
718f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
719ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
720ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
721ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
723ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
724ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
72802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
72902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
73002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
73102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
732f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
73302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
73444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
73502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
73602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
73702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
73802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
73902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
7401201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
74102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
74202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
74302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
74402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
74502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
74602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
74702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
74802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
74902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
75002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
75102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
752cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
75302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
75402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
75502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
75602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
75702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
75802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
75902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
76002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
76102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
76202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
76302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
76402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
76502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
76630145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
76702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
76802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
76902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
7704f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			const char *colon = strchr(path, ':');
7714f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (colon) {
7724f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				n = colon - path;
77302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
77402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
77502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
77602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
77702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
77802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
77902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
78002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
78102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
78202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
78302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
78402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
78502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
78602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
78702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
78802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
78902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
79002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
79102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
79202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
79302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
79402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
79502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
79602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
79702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
79802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
79902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
80002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
801cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
80202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
803a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
804ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
805cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
806ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
80775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
80875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
809ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
810ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
8112e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		if (outf != stderr)
8122e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			close(fileno(outf));
81331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!daemonized_tracer && !use_seize) {
81431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
815cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
816ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
81702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
81802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
819ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
82002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
82102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
82202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
82302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
82402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
82502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
82602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
82702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
82802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
82902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
83002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
831ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
832ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
833ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
834ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
835ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
836ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
837ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
838ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
83902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
84002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
841ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
84202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
84302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
844ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
845ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
8462e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
847ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
8482e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
8492e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
8502e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
851ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
852c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
8532e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
854ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
855ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
856ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
857ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
858ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
859ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
860ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
861ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
862ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
863ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
864ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
865ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
866ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
867ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
868ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
869ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
870ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
87102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
87202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
873cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
87402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
875ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
8762e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
87775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
8782e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
87931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!use_seize) {
88031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* child did PTRACE_TRACEME, nothing to do in parent */
88131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		} else {
88231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked) {
88331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* Wait until child stopped itself */
88431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				int status;
88531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				while (waitpid(pid, &status, WSTOPPED) < 0) {
88631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (errno == EINTR)
88731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko						continue;
88831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("waitpid");
88931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
89031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
89175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko					kill_save_errno(pid, SIGKILL);
89231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("Unexpected wait status %x", status);
89331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
89431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
89531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Else: vforked case, we have no way to sync.
89631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * Just attach to it as soon as possible.
89731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * This means that we may miss a few first syscalls...
89831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
89931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
90031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace_attach_or_seize(pid)) {
90175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				kill_save_errno(pid, SIGKILL);
90231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				perror_msg_and_die("Can't attach to %d", pid);
90331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
90431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked)
90531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGCONT);
90631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
9072e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
908f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
90975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
910f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
91175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
9122e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
9132e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
9142e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
9152e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
9162e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
9172e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
918f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		alloctcb(pid);
919f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		/* attaching will be done later, by startup_attach */
920ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
92102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
92202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
923b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
924b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
925b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
926b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
927b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
92804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
9293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
930b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
9312fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
9322fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
9332fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
9342fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
935b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
9365d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
9375d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
93804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
9395d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
94004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
94131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
94204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
94304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
9444c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko		kill_save_errno(pid, SIGSTOP);
94504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
94604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
94704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
948b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
949b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
950b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
951b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
952b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
95304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
954b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
95504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
956b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
957b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
9584c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			if (errno == ECHILD)
959b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
96004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
96104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
96204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
96304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
96404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
96504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
96604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
96704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
96804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
96904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
97004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
97104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
97204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
97304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
97404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
97504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
97604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
97704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
97804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
97904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
98004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
98104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
9824c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			kill_save_errno(pid, SIGKILL);
98304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
98404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
985b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
986b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
9872fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
98804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
98904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
99004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
99104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
99204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
99304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
994b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
99504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
99604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
99704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
99804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
99904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
100004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
100104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
100204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
100304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
10042fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
100504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
100604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
100704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
1008b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
100904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
101004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
101104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
101204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
101304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
1014b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
1015b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
101604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
1017f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1018a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
101904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
102004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
102104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
102204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
102304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
102404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
1025b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
10263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
10283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
10293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
10303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
10313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
10323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
10333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
10343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
10353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
10363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
10373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
10383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
10393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
10403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
10413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
10423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
10433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
104404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
104504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
10463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
10473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
10483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
10503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
105175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
10523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
10543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
10553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
105675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
105704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
105804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
10593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
10603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
10613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
10643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
10653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
10673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
10683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
10693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
10703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
107104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
107204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
107304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
107475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
107575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
107675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
107775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
107804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
107904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
108004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
108104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
108204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
108304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
10843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
10863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
108704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
108804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
10893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
10913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
10923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
10933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
10943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
10953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
10963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
109704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
109804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
109904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
11003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
11023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
11033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
110504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
110675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
11073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
11093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
11103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
111175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
1112f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1113a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
1114f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1115f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
11163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
11173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
11183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
111904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
112004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
11213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
112231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
112331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# ifdef USE_SEIZE
112431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void
112531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void)
112631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
112731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int pid;
112831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
112931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	pid = fork();
113031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid < 0)
113131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		perror_msg_and_die("fork");
113231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
113331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid == 0) {
113431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		pause();
113531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		_exit(0);
113631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
113731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
113831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	/* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap.  After
113931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * attaching tracee continues to run unless a trap condition occurs.
114031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * PTRACE_SEIZE doesn't affect signal or group stop state.
114131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 */
114231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
114331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
1144a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko	} else if (debug_flag) {
114531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
114631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
114731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
114831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	kill(pid, SIGKILL);
114931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
115031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	while (1) {
115131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int status, tracee_pid;
115231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
115331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		errno = 0;
115431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tracee_pid = waitpid(pid, &status, 0);
115531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (tracee_pid <= 0) {
115631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (errno == EINTR)
115731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
115831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d",
115931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					 __func__, tracee_pid);
116031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
116131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (WIFSIGNALED(status)) {
116231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			return;
116331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
116431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		error_msg_and_die("%s: unexpected wait status %x",
116531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				__func__, status);
116631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
116731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
116831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# else /* !USE_SEIZE */
116931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#  define test_ptrace_seize() ((void)0)
117031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# endif
117131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
11726e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned
1173f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void)
1174f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{
11756e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	unsigned rel;
11766e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	const char *p;
1177f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	struct utsname u;
1178f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (uname(&u) < 0)
1179f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		perror_msg_and_die("uname");
11806e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	/* u.release has this form: "3.2.9[-some-garbage]" */
11816e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	rel = 0;
11826e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	p = u.release;
11836e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	for (;;) {
11846e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (!(*p >= '0' && *p <= '9'))
11856e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
11866e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		/* Note: this open-codes KERNEL_VERSION(): */
11876e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		rel = (rel << 8) | atoi(p);
11886e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (rel >= KERNEL_VERSION(1,0,0))
11896e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			break;
11906e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		while (*p >= '0' && *p <= '9')
11916e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			p++;
11926e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (*p != '.')
11936e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
11946e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		p++;
11956e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	}
11966e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	return rel;
1197f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko}
1198f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1199ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko/*
1200ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Initialization part of main() was eating much stack (~0.5k),
1201ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * which was unused after init.
1202ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * We can reuse it if we move init code into a separate function.
1203ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko *
1204ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Don't want main() to inline us and defeat the reason
1205ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * we have a separate function.
1206ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko */
1207ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void __attribute__ ((noinline))
1208ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoinit(int argc, char *argv[])
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
1211e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	int c;
121206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
121508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
121608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
121775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
121875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
12196e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	os_release = get_os_release();
1220f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1221ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
1222ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
12234f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
12241d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
12251d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
12264f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
12271d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
12281d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
12294f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
12304f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
1231ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
1233138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
1234138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
124061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		"+bcCdfFhiqrtTvVxyz"
1241ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1242b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
124461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		case 'b':
124561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			detach_on_execve = 1;
124661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			break;
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1248e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1249cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1250e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1251e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1252e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1253e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1254e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1255cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1256e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1257e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
1260a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			debug_flag = 1;
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1262ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1263ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1264ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
126541c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
126606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
126706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
1275a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			iflag = 1;
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
1278a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			qflag = 1;
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
1281a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			rflag = 1;
1282a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			/* fall through to tflag++ */
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
1287a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			Tflag = 1;
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
12928a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
12938a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
12948a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
12999c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
130217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
130317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
130417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
1307102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1308102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				error_msg_and_die("Bad column width '%s'", optarg);
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1320e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			process_opt_p_list(optarg);
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
13228a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
13238a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
13248a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1325cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
13268a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
13278a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1330dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1331b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1332dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1340de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
13411d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
13421d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1343de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
1344b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		case 'I':
1345b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = atoi(optarg);
1346b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1347b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1348b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			}
1349b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			break;
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1355837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1356837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1358102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1359102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
13601d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1361102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1362102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1363102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1364837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1365fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (!argv[0] == !nprocs)
1366ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1367ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1368fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 && daemonized_tracer) {
1369cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1370d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1371d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
137206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
137306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
137406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1375cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1376cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1377cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1378cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
138076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1384cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
13865d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
13875d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1388cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
139904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
14003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
140131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	test_ptrace_seize();
14028044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
140537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
140637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
140737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
140837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
140937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
141037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
14117dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
14127dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
14137dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
141454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
14153d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
14163d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
1417328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko	} else {
1418328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		/* -ff without -o FILE is the same as single -f */
1419328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		if (followfork > 1)
1420328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko			followfork = 1;
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1423cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1424a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1425a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1426a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1428cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1429837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
1430b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (!opt_intr)
1431b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = INTR_NEVER;
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1433369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1434b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (!opt_intr)
1435b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		opt_intr = INTR_WHILE_WAIT;
1436b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
1437b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	/* argv[0]	-pPID	-oFILE	Default interactive setting
1438b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	0	INTR_WHILE_WAIT
1439b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	0	INTR_WHILE_WAIT
1440b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	1	INTR_NEVER
1441b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	1	INTR_WHILE_WAIT
144254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
144354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
144454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
144554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
144654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
144754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
144861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	if (argv[0]) {
144961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		skip_startup_execve = 1;
1450837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
145161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	}
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
1458b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1459b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1460b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (opt_intr != INTR_ANYWHERE) {
1461b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_BLOCK_TSTP_TOO)
1462b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1463b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/*
1464b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1465b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * fatal signals are blocked while syscall stop is processed,
1466b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * and acted on in between, when waiting for new syscall stops.
1467b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In non-interactive mode, signals are ignored.
1468b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 */
1469b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_WHILE_WAIT) {
1470b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGHUP);
1471b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGINT);
1472b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGQUIT);
1473b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGPIPE);
1474b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGTERM);
1475b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_handler = interrupt;
1476b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		}
1477b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/* SIG_IGN, or set handler for these */
1478b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGHUP, &sa, NULL);
1479b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGINT, &sa, NULL);
1480b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGQUIT, &sa, NULL);
1481b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGPIPE, &sa, NULL);
1482b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGTERM, &sa, NULL);
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1484553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1485553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1486553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1487553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1488553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1489553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1490553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1492fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 || daemonized_tracer)
149302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
149402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1495fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	/* Do we want pids printed in our -o OUTFILE?
1496fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -ff: no (every pid has its own file); or
1497fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -f: yes (there can be more pids in the future); or
1498fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -p PID1,PID2: yes (there are already more than one pid)
1499fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 */
1500fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15032b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1504418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
15057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
15067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
15077b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
15087b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
15097b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
15107b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
151118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
151218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
151318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
15141d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!newtab || !newtcbs)
15151d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
15167b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
15177b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
151818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
151918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
15207b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
15217b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
152310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1528418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1529418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1530418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1531ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1532ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
153418da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1536381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko			tcp->flags = TCB_INUSE;
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1538a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#if SUPPORTED_PERSONALITIES > 1
1539a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin			tcp->currpers = current_personality;
1540a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#endif
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
1542a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
15431d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
154410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
154510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1552eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
155354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
155654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
155754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
155854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1560ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
156154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
156254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
156554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15701201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
157419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
1576a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko	if (debug_flag)
15771d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1578eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
15793e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko	if (tcp->outf) {
15803e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko		if (outfname && followfork >= 2) {
15813e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			if (tcp->curcol != 0)
15823e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko				fprintf(tcp->outf, " <detached ...>\n");
15833e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			fclose(tcp->outf);
15843e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			if (outf == tcp->outf)
15853e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko				outf = NULL;
15863e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko		} else {
15873e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			if (printing_tcp == tcp && tcp->curcol != 0)
15883e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko				fprintf(tcp->outf, " <detached ...>\n");
15893e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			fflush(tcp->outf);
15903e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko		}
15913e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko	}
15923e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko
15937de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (printing_tcp == tcp)
15947de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		printing_tcp = NULL;
15957de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
159619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15990a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
160075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * Never call DETACH twice on the same process as both unattached and
160175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * attached-unstopped processes give the same ESRCH.  For unattached process we
160275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * would SIGSTOP it and wait for its SIGSTOP notification forever.
160375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko */
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16054c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkodetach(struct tcb *tcp)
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
160775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int error;
160875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int status, sigstop_expected;
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1611840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16157bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16217bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
162275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
16233e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko	error = 0;
162475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	sigstop_expected = 0;
162575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (tcp->flags & TCB_ATTACHED) {
162675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		/*
162775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * We attached but possibly didn't see the expected SIGSTOP.
162875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * We must catch exactly one as otherwise the detached process
162975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * would be left stopped (process state T).
163075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 */
163175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
163275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
163375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (error == 0) {
163475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			/* On a clear day, you can see forever. */
163575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
163675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (errno != ESRCH) {
163775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			/* Shouldn't happen. */
163875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			perror("detach: ptrace(PTRACE_DETACH, ...)");
163975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
164075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (my_tkill(tcp->pid, 0) < 0) {
164175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			if (errno != ESRCH)
164275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				perror("detach: checking sanity");
164375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
164475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
164575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			if (errno != ESRCH)
164675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				perror("detach: stopping child");
164775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
164875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else
164975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			sigstop_expected = 1;
16507bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
165175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
165275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (sigstop_expected) {
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
16547508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
165537ab4b79de57c1657e41f96a96fa699a08194a80Denys Vlasenko			if (waitpid(tcp->pid, &status, __WALL) < 0) {
16567508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16577508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16587508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16607508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16617508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16627508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16637508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16647508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16657508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16667508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16677508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16687508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16697508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
16707508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
167137ab4b79de57c1657e41f96a96fa699a08194a80Denys Vlasenko					if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
16727508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16737508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16747508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16757508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16767508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16777508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16787508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16807508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
16864c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, 0);
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1689732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
169075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1691732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1692732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1695ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (!qflag && (tcp->flags & TCB_ATTACHED))
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1701a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17061201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
17103521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	int fatal_sig;
17113521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko
17123521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	/* 'interrupted' is a volatile object, fetch it only once */
17133521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	fatal_sig = interrupted;
17143521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	if (!fatal_sig)
17153521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko		fatal_sig = SIGTERM;
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1717ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1718ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
1721a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
17247de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (tcp->flags & TCB_STRACE_CHILD) {
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
1726a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko			kill(tcp->pid, fatal_sig);
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17287de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		detach(tcp);
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17351201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
1737a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko	interrupted = sig;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17426d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17456d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
17481201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17501945ccc3fbd5b56008c4a6b0cdd4611616201675Denys Vlasenko	static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175235aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
175335aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175635aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17638f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
17646d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
17668f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
17678f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
17688f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
17711201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17731945ccc3fbd5b56008c4a6b0cdd4611616201675Denys Vlasenko	static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
17891201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
179226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
179326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
1794eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
179526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1797eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
1798f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int pid;
1799f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int wait_errno;
1800f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int status, sig;
180131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int stopped;
1802f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		struct tcb *tcp;
1803f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		unsigned event;
1804f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1805222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
1806eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
1807eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1808eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
180926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
181026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
18115bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
18122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
18132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
181426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
18152f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
18165bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
18172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
181826d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
181926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
1820cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
18212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
18222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
182326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
182426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
182526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
1827eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1828eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
1831eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
1832eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1834eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
1841eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
1842eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
1843eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
18444c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("wait");
1845eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
184810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
184910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
18507dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
185110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
185210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
1853f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1854f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		event = ((unsigned)status >> 16);
1855a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag) {
18561d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
185767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
18581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
18591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
18601d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
18611d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
18621d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
18631d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18641d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
18651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
18661d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
18681d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
18691d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
18701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
18711d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
18725bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
18731d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
18741d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
18755bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
187667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			evbuf[0] = '\0';
187767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			if (event != 0) {
187867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				static const char *const event_names[] = {
187967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
188067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
188167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
188267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
188367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
188467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
188567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				};
188667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				const char *e;
188767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				if (event < ARRAY_SIZE(event_names))
188867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = event_names[event];
188967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				else {
189067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					sprintf(buf, "?? (%u)", event);
189167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = buf;
189267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				}
189367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				sprintf(evbuf, ",PTRACE_EVENT_%s", e);
189467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			}
189567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
18961d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1898f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Look up 'pid' in our table. */
18995d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
1900f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1901f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Under Linux, execve changes pid to thread leader's pid,
1902f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and we see this changed pid on EVENT_EXEC and later,
1903f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * execve sysexit. Leader "disappears" without exit
1904f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * notification. Let user know that, drop leader's tcb,
1905f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and fix up pid in execve thread's tcb.
1906f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * Effectively, execve thread's tcb replaces leader's tcb.
1907f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1908f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1909f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * on exit syscall) in multithreaded programs exactly
1910f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * in order to handle this case.
1911f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1912f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1913f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * On 2.6 and earlier, it can return garbage.
1914f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 */
19156e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
1916f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			long old_pid = 0;
1917f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1918f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid > 0
1919f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid != pid
1920f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			) {
1921f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				struct tcb *execve_thread = pid2tcb(old_pid);
1922f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
1923f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					outf = tcp->outf;
1924f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					curcol = tcp->curcol;
1925f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					if (execve_thread) {
19267de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						if (execve_thread->curcol != 0) {
19277de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							/*
19287de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							 * One case we are here is -ff:
19297de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							 * try "strace -oLOG -ff test/threaded_execve"
19307de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							 */
19317de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
19327de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							execve_thread->curcol = 0;
19337de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						}
1934f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						/* swap output FILEs (needed for -ff) */
1935f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						tcp->outf = execve_thread->outf;
19367de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						tcp->curcol = execve_thread->curcol;
1937f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						execve_thread->outf = outf;
19387de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						execve_thread->curcol = curcol;
1939f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					}
1940f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					droptcb(tcp);
1941f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
1942f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				tcp = execve_thread;
1943f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
1944f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->pid = pid;
1945f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->flags |= TCB_REPRINT;
19467de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko					if (!cflag) {
19477de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						printleader(tcp);
19487de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
19497de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						line_ended();
19507de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko					}
1951f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
1952f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			}
1953f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		}
1954f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
195561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
195661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			if (!skip_startup_execve)
195761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko				detach(tcp);
195861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			/* This was initial execve for "strace PROG". Skip. */
195961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			skip_startup_execve = 0;
196061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		}
196161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
19625d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
196341c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
1964e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
1965e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
1966e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
1967e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
1968e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
1969e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
1970e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
1971e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
1972e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
1973418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
197431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
1975e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
1976833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
1977e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
19788b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
1979e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
1980e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
1981e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
1982e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
1983e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
198497c503fa2e9cd02126feae659f133631c8eb36f1Denys Vlasenko					ptrace(PTRACE_CONT, pid, (char *) 0, 0);
1985cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
1986e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19887de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
19897de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		/* Set current output file */
1990eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
1991ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
19927de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
199313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1997eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
1999a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2000a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2001e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
200413d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
2005000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s %s+++\n",
20062efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
200713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
200813d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
2009000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s +++\n",
201013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
20112efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
20127de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2018a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2019a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
202019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
202119cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
2022000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
20237de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
202419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2034f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
2035f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
2036a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2037f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
203902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
204102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
20422ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
20446cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
20456cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
205144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
2052a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko				if (debug_flag)
205344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
205444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
205544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
205644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
205744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
20583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
20593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
20603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2061f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2062f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
206331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		sig = WSTOPSIG(status);
206431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
2065f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event != 0) {
206631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Ptrace event */
206731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
206831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
20696703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				/*
20706703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop or group-stop.
20716703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
20726703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 */
207331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (sig == SIGSTOP
207431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTSTP
207531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTIN
207631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTOU
207731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				) {
207831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					stopped = 1;
207931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					goto show_stopsig;
208031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
208131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
208231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
2083f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2084f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2085f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2086f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2087f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2088f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2089f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2090f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2091f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2092f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2093a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2094f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2095f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
20966cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20996cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
210031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			siginfo_t si;
210131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
210231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Nonzero (true) if tracee is stopped by signal
210331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * (as opposed to "tracee received signal").
210431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
210531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
21066703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#ifdef USE_SEIZE
210731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig:
21086703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif
2109e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
21106cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2111c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
21126b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
21136b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
21147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2115932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2116932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
21177b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
21186b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
21197b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
21206b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
21212ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
21226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
21232ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
21242ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
21257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
212731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!stopped) {
212860fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("--- ");
21296b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
2130000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprintf(" (%s)" PC_FORMAT_STR " ---\n",
21316cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig)
21326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
21336b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
2134000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
21356cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig),
21366cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
21376b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
21387de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
214131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!stopped)
214231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* It's signal-delivery-stop. Inject the signal */
214331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				goto restart_tracee;
214431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
214531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* It's group-stop */
214631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
214731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (use_seize) {
214831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/*
214931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This ends ptrace-stop, but does *not* end group-stop.
215031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This makes stopping signals work properly on straced process
215131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * (that is, process really stops. It used to continue to run).
215231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 */
215331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
215431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cleanup();
215531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					return -1;
215631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
21577de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				tcp->curcol = curcol;
215831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
215931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
216031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* We don't have PTRACE_LISTEN support... */
216131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
21626cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21642ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
21652ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
216602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
216702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
21682ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
21692ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
21702ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
21712ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
21722ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2173eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2174eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2175eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2176eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2177f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
21787de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * We assume that ptrace error was caused by process death.
2179f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * We used to detach(tcp) here, but since we no longer
2180f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * implement "detach before death" policy/hack,
2181f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * we can let this process to report its death to us
2182f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * normally, via WIFEXITED or WIFSIGNALED wait status.
2183f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 */
21847de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			tcp->curcol = curcol;
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21876cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
21886cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
21896cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2190ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2191ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
21926cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
2199ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2200ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoint
2201ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkomain(int argc, char *argv[])
2202ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko{
2203ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	init(argc, argv);
2204ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2205ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	/* Run main tracing loop */
2206ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (trace() < 0)
2207ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		return 1;
2208ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2209ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	cleanup();
2210ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	fflush(NULL);
2211ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (exit_code > 0xff) {
2212ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Avoid potential core file clobbering.  */
2213ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		struct rlimit rlim = {0, 0};
2214ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		setrlimit(RLIMIT_CORE, &rlim);
2215ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2216ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Child was killed by a signal, mimic that.  */
2217ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code &= 0xff;
2218ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		signal(exit_code, SIG_DFL);
2219ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		raise(exit_code);
2220ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Paranoia - what if this signal is not fatal?
2221ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		   Exit with 128 + signo then.  */
2222ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code += 128;
2223ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	}
2224ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2225ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	return exit_code;
2226ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko}
2227