strace.c revision a509054aeee00a89a2250919f74bd849c67ded61
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
1612c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#ifndef HAVE_STRERROR
1622c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1632c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#if !HAVE_DECL_SYS_ERRLIST
1642c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern int sys_nerr;
1652c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern char *sys_errlist[];
1662c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#endif /* HAVE_DECL_SYS_ERRLIST */
1672c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1682c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoconst char *
1692c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkostrerror(int err_no)
1702c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko{
1712c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
1722c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1732c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
1742c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
1752c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko		return buf;
1762c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	}
1772c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	return sys_errlist[err_no];
1782c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko}
1792c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1802c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#endif /* HAVE_STERRROR */
1812c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
183cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
186b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkousage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
187b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko              [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
188cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko              [-P path] [PROG [ARGS]]\n\
189b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
190cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko              [PROG [ARGS]]\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
192b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
1933e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-d -- enable debug output to stderr\n\
194b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
1963e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-F -- attempt to follow vforks (deprecated, use -f)\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
198b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-I interruptible\n\
199b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   1: no signals are blocked\n\
200b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   2: fatal signals are blocked while decoding syscall (default)\n\
201b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   3: fatal signals are always blocked (default if '-o FILE PROG')\n\
202b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   4: fatal signals and SIGTSTP (^Z) are always blocked\n\
203b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko      (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
206cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-T -- print time spent in each syscall\n\
207cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
2098a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
210cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-h -- print help message\n\
211cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-V -- print version\n\
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
221de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
222de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2238a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
22461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko"
22561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* this is broken, so don't document it
22617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
22761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */
22861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* experimental, don't document it yet (option letter may change in the future!)
22961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko-b -- detach on successful execve\n\
23061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */
231de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
23575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
23675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
23775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
24075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
24175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
24275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
24782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	char *msg;
24882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
24944d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
25082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
25182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We want to print entire message with single fprintf to ensure
25282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * message integrity if stderr is shared with other programs.
25382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * Thus we use vasprintf + single fprintf.
25482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 */
25582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	msg = NULL;
256cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko	if (vasprintf(&msg, fmt, p) >= 0) {
25782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
25882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
25982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
26082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
26182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		free(msg);
26282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	} else {
26382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		/* malloc in vasprintf failed, try it without malloc */
26482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		fprintf(stderr, "%s: ", progname);
26582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		vfprintf(stderr, fmt, p);
26682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
26782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, ": %s\n", strerror(err_no));
26882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
26982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			putc('\n', stderr);
27082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	}
27182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We don't switch stderr to buffered, thus fprintf(stderr)
27282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * always flushes its output and this is not necessary: */
27382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* fflush(stderr); */
27475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
27575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
27675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
27775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
27875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
27975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
28075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
28275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2833454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
28475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
28575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
28675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
28775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
28875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
28975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
29075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
29175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
29275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
29375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
29475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
29575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
29675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
29775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
29875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
29975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
30075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
30175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
30275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
30375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
30475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
30575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
3063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
3073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
3081d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
3091d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
3101d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
3111d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
3121d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
3131d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
3141d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
3151d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
3161d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
317c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
318c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
319c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
320c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
321c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
322c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
323c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
324c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
32531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
32631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int
32731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid)
32831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
32931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int r;
33031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (!use_seize)
33131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return ptrace(PTRACE_ATTACH, pid, 0, 0);
33231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
33331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (r)
33431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return r;
33531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
33631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	return r;
33731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
33831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
33931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
34031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
34131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
3421f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3451f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
3461f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
3471f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
3481f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
3491f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
3501f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
3511f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
3521f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
3531f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
3541f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3591f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3611f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenkostatic void kill_save_errno(pid_t pid, int sig)
36575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko{
36675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int saved_errno = errno;
36775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
36875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	(void) kill(pid, sig);
36975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	errno = saved_errno;
37075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko}
37175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
3722e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprintf(const char *fmt, ...)
3742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_list args;
3762e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3772e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_start(args, fmt);
3782e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (outf) {
3792e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		int n = vfprintf(outf, fmt, args);
3802e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n < 0) {
3812e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (outf != stderr)
3822e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				perror(outfname == NULL
3832e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				       ? "<writing to pipe>" : outfname);
3842e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		} else
3852e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			curcol += n;
3862e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
3872e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_end(args);
3882e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
3892e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
3902e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
3912e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprints(const char *str)
3922e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
3932e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (outf) {
3942e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		int n = fputs(str, outf);
3952e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n >= 0) {
3962e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			curcol += strlen(str);
3972e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			return;
3982e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
3992e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (outf != stderr)
4002e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			perror(outfname == NULL
4012e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			       ? "<writing to pipe>" : outfname);
4022e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
4032e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4042e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4052e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
4067de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkoline_ended(void)
4077de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko{
4087de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	curcol = 0;
4097de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	fflush(outf);
4107de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (!printing_tcp)
4117de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		return;
4127de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	printing_tcp->curcol = 0;
4137de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	printing_tcp = NULL;
4147de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko}
4157de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
4167de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkovoid
4172e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkoprintleader(struct tcb *tcp)
4182e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
4197de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	/* If -ff, "previous tcb we printed" is always the same as current,
4207de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	 * because we have per-tcb output files.
4217de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	 */
4227de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (followfork >= 2)
4237de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		printing_tcp = tcp;
4247de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
4252e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (printing_tcp) {
4267de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		outf = printing_tcp->outf;
4277de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		curcol = printing_tcp->curcol;
4282e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (printing_tcp->ptrace_errno) {
4292e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (printing_tcp->flags & TCB_INSYSCALL) {
4302e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprints(" <unavailable>) ");
4312e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tabto();
4322e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			}
4332e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints("= ? <unavailable>\n");
4342e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			printing_tcp->ptrace_errno = 0;
4357de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->curcol = 0;
4367de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		}
4377de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
4387de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			/*
4397de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * case 1: we have a shared log (i.e. not -ff), and last line
4407de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * wasn't finished (same or different tcb, doesn't matter).
4417de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * case 2: split log, we are the same tcb, but our last line
4427de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
4437de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 */
4442e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints(" <unfinished ...>\n");
4457de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->flags |= TCB_REPRINT;
4467de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->curcol = 0;
4472e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4482e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
4492e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4502e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	printing_tcp = tcp;
4517de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	outf = tcp->outf;
4522e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	curcol = 0;
4532e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4542e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (print_pid_pfx)
4552e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("%-5d ", tcp->pid);
4562e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	else if (nprocs > 1 && !outfname)
4572e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("[pid %5u] ", tcp->pid);
4582e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4592e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (tflag) {
4602e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		char str[sizeof("HH:MM:SS")];
4612e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		struct timeval tv, dtv;
4622e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		static struct timeval otv;
4632e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4642e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		gettimeofday(&tv, NULL);
4652e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (rflag) {
4662e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (otv.tv_sec == 0)
4672e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				otv = tv;
4682e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tv_sub(&dtv, &tv, &otv);
4692e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%6ld.%06ld ",
4702e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) dtv.tv_sec, (long) dtv.tv_usec);
4712e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			otv = tv;
4722e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else if (tflag > 2) {
4742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%ld.%06ld ",
4752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) tv.tv_sec, (long) tv.tv_usec);
4762e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4772e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else {
4782e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			time_t local = tv.tv_sec;
4792e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			strftime(str, sizeof(str), "%T", localtime(&local));
4802e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (tflag > 1)
4812e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
4822e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			else
4832e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s ", str);
4842e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
4852e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
4862e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (iflag)
4872e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		printcall(tcp);
4882e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4892e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
4902e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
4912e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotabto(void)
4922e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
4932e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (curcol < acolumn)
4942e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprints(acolumn_spaces + curcol);
4952e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
4962e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
49710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
49810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
49910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
50010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
50110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
50210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
50310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
50410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
50510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5067b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
507cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
50810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
50910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
51010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5114bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
5124bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
5134bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
5144bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
5154bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
5164bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
51710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
5183d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
51910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
52010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
52110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
52210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
5233d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
5243d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
5253d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
52610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
5273d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
52810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
52910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
53010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5317dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
53210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
53310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
53410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
53510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
53610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
53710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
53810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
53910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
54010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
54110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
54210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
54310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
54410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
5457dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
5467dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
54710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
54810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
54910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
5507dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
55110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5527dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
55310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5547dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
5557dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
5567dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
55710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5587dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
55910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
56010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
5617dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
5627dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
5637dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
5647dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
56510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
56610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
5677dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
56810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
5697dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
5707dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
5717dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
5727dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
5737dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
5747dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
5751d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
5767dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
57710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
57810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
5793d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
58010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
58110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
5827de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (outfname && followfork >= 2) {
5837a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
5847a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
5853d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
58610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
58710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
58810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
589558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkostatic void
590558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkoprocess_opt_p_list(char *opt)
591e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko{
592e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	while (*opt) {
593e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		/*
594e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
595e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * pidof uses space as delim, pgrep uses newline. :(
596e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 */
597e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		int pid;
598e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char *delim = opt + strcspn(opt, ", \n\t");
599e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char c = *delim;
600e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
601e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = '\0';
602e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		pid = atoi(opt); /* TODO: stricter parsing of the number? */
603e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid <= 0) {
604e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			error_msg("Invalid process id: '%s'", opt);
605e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			*delim = c;
606e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			return;
607e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
608e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid == strace_tracer_pid) {
609e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			error_msg("I'm sorry, I can't let you do that, Dave.");
610e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			*delim = c;
611e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			return;
612e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
613e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = c;
61475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		alloc_tcb(pid, 0);
615e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (c == '\0')
616e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			break;
617e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		opt = delim + 1;
618e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	}
619e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko}
620e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
6302e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
631b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
636ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
637ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
638ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
639014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
640ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
64375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
64475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
64575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
65175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
65275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
65375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
65844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
65975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (!(tcp->flags & TCB_INUSE))
66075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue;
66175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
662d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
66375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (tcp->flags & TCB_ATTACHED)
66475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue; /* no, we already attached it */
665d116a7338645af45090aecc331701e999148d284Denys Vlasenko
666d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Reinitialize the output since it may have changed */
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
6683d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
670ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
6717a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
67602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
67702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
679381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
68002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
681381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
682381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
683381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
6847a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
68702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
69031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (ptrace_attach_or_seize(tid) < 0) {
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
692a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko						if (debug_flag)
693f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
694381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
695f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
696a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko					if (debug_flag)
697381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
698381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
699381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
700381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
70131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
70202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
704381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
705381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
706381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
707381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
708381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
709381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
7107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
7117a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
71202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
71302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
71402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
71502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
71602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
7177a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
7187a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
7197a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
72044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
72102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
72275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				if (!(tcp->flags & TCB_ATTACHED)) {
723f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
724f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
725f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
726f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
727f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
728f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
72902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
7307a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
7317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
73231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace_attach_or_seize(tcp->pid) < 0) {
73302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
73402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
73502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
73602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
73775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
738a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
739f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
740ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
741ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
742ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
743ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
744ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
745ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
746ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
747ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
748ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
74902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
75002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
75102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
75202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
753f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
75402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
75544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
75602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
75702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
75802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
75902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
76002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
7611201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
76202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
76302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
76402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
76502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
76602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
76702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
76802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
76902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
77002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
77102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
77202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
773cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
77402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
77502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
77602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
77702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
77802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
77902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
78002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
78102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
78202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
78302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
78402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
78502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
78602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
78730145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
78802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
78902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
79002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
7914f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			const char *colon = strchr(path, ':');
7924f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (colon) {
7934f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				n = colon - path;
79402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
79502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
79602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
79702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
79802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
79902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
80002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
80102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
80202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
80302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
80402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
80502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
80602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
80702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
80802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
80902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
81002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
81102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
81202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
81302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
81402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
81502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
81602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
81702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
81802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
81902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
82002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
82102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
822cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
82302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
824a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
825ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
826cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
827ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
82875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
82975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
830ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
831ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
8322e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		if (outf != stderr)
8332e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			close(fileno(outf));
83431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!daemonized_tracer && !use_seize) {
83531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
836cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
837ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
83802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
83902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
840ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
84102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
84202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
84302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
84402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
84502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
84602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
84702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
84802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
84902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
85002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
85102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
852ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
853ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
854ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
855ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
856ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
857ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
858ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
859ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
86002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
86102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
862ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
86302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
86402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
865ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
866ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
8672e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
868ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
8692e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
8702e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
8712e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
872ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
873c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
8742e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
875ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
876ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
877a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko			/* we depend on SIGCHLD set to SIG_DFL by init code */
878a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko			/* if it happens to be SIG_IGN'ed, wait won't block */
879ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
880ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
881ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
88202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
88302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
884cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
88502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
886ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
8872e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
88875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
8892e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
89031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!use_seize) {
89131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* child did PTRACE_TRACEME, nothing to do in parent */
89231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		} else {
89331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked) {
89431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* Wait until child stopped itself */
89531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				int status;
89631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				while (waitpid(pid, &status, WSTOPPED) < 0) {
89731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (errno == EINTR)
89831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko						continue;
89931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("waitpid");
90031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
90131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
90275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko					kill_save_errno(pid, SIGKILL);
90331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("Unexpected wait status %x", status);
90431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
90531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
90631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Else: vforked case, we have no way to sync.
90731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * Just attach to it as soon as possible.
90831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * This means that we may miss a few first syscalls...
90931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
91031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
91131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace_attach_or_seize(pid)) {
91275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				kill_save_errno(pid, SIGKILL);
91331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				perror_msg_and_die("Can't attach to %d", pid);
91431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
91531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked)
91631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGCONT);
91731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
9182e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
919f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
92075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
921f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
92275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
9232e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
9242e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
9252e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
9262e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
9272e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
9282e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
929f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		alloctcb(pid);
930f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		/* attaching will be done later, by startup_attach */
931ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
93202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
93302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
934b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
935b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
936b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
937b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
938b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
93904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
9403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
941b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
9422fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
9432fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
9442fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
9452fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
946b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
9475d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
9485d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
94904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
9505d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
95104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
95231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
95304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
95404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
9554c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko		kill_save_errno(pid, SIGSTOP);
95604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
95704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
95804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
959b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
960b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
961b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
962b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
963b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
96404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
965b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
96604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
967b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
968b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
9694c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			if (errno == ECHILD)
970b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
97104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
97204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
97304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
97404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
97504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
97604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
97704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
97804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
97904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
98004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
98104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
98204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
98304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
98404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
98504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
98604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
98704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
98804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
98904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
99004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
99104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
99204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
9934c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			kill_save_errno(pid, SIGKILL);
99404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
99504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
996b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
997b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
9982fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
99904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
100004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
100104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
100204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
100304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
100404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
1005b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
100604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
100704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
100804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
100904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
101004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
101104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
101204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
101304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
101404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
10152fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
101604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
101704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
101804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
1019b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
102004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
102104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
102204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
102304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
102404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
1025b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
1026b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
102704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
1028f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1029a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
103004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
103104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
103204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
103304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
103404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
103504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
1036b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
10373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
10393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
10403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
10413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
10423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
10433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
10443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
10453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
10463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
10473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
10483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
10493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
10503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
10513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
10523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
10533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
10543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
105504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
105604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
10573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
10583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
10593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
10613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
106275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
10633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
10653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
10663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
106775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
106804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
106904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
10703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
10713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
10723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
10753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
10763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
10783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
10793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
10803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
10813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
108204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
108304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
108404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
108575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
108675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
108775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
108875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
108904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
109004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
109104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
109204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
109304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
109404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
10953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
10973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
109804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
109904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
11003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
11023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
11033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
11043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
11053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
11063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
11073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
110804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
110904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
111004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
11113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
11133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
11143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
111604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
111775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
11183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
11193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
11203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
11213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
112275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
1123f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1124a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
1125f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1126f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
11273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
11283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
11293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
113004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
113104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
11323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
113331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
113431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# ifdef USE_SEIZE
113531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void
113631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void)
113731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
113831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int pid;
113931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
114031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	pid = fork();
114131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid < 0)
114231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		perror_msg_and_die("fork");
114331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
114431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid == 0) {
114531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		pause();
114631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		_exit(0);
114731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
114831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
114931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	/* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap.  After
115031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * attaching tracee continues to run unless a trap condition occurs.
115131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * PTRACE_SEIZE doesn't affect signal or group stop state.
115231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 */
115331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
115431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
1155a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko	} else if (debug_flag) {
115631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
115731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
115831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
115931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	kill(pid, SIGKILL);
116031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
116131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	while (1) {
116231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int status, tracee_pid;
116331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
116431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		errno = 0;
116531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tracee_pid = waitpid(pid, &status, 0);
116631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (tracee_pid <= 0) {
116731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (errno == EINTR)
116831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
116931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d",
117031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					 __func__, tracee_pid);
117131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
117231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (WIFSIGNALED(status)) {
117331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			return;
117431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
117531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		error_msg_and_die("%s: unexpected wait status %x",
117631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				__func__, status);
117731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
117831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
117931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# else /* !USE_SEIZE */
118031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#  define test_ptrace_seize() ((void)0)
118131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# endif
118231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
11836e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned
1184f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void)
1185f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{
11866e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	unsigned rel;
11876e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	const char *p;
1188f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	struct utsname u;
1189f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (uname(&u) < 0)
1190f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		perror_msg_and_die("uname");
11916e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	/* u.release has this form: "3.2.9[-some-garbage]" */
11926e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	rel = 0;
11936e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	p = u.release;
11946e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	for (;;) {
11956e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (!(*p >= '0' && *p <= '9'))
11966e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
11976e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		/* Note: this open-codes KERNEL_VERSION(): */
11986e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		rel = (rel << 8) | atoi(p);
11996e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (rel >= KERNEL_VERSION(1,0,0))
12006e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			break;
12016e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		while (*p >= '0' && *p <= '9')
12026e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			p++;
12036e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (*p != '.')
12046e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
12056e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		p++;
12066e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	}
12076e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	return rel;
1208f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko}
1209f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1210ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko/*
1211ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Initialization part of main() was eating much stack (~0.5k),
1212ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * which was unused after init.
1213ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * We can reuse it if we move init code into a separate function.
1214ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko *
1215ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Don't want main() to inline us and defeat the reason
1216ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * we have a separate function.
1217ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko */
1218ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void __attribute__ ((noinline))
1219ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoinit(int argc, char *argv[])
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
1222e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	int c;
122306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
122608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
122708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
1228a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	/* Make sure SIGCHLD has the default action so that waitpid
1229a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   definitely works without losing track of children.  The user
1230a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   should not have given us a bogus state to inherit, but he might
1231a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   have.  Arguably we should detect SIG_IGN here and pass it on
1232a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   to children, but probably noone really needs that.  */
1233a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	signal(SIGCHLD, SIG_DFL);
1234a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko
123575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
123675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
12376e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	os_release = get_os_release();
1238f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1239ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
1240ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
12414f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
12421d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
12431d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
12444f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
12451d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
12461d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
12474f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
12484f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
1249ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
1251138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
1252138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
125861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		"+bcCdfFhiqrtTvVxyz"
1259ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1260b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
126261e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		case 'b':
126361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			detach_on_execve = 1;
126461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			break;
126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1266e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1267cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1268e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1269e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1270e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1271e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1272e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1273cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1274e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1275e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
1278a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			debug_flag = 1;
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1280ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1281ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1282ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
128341c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
128406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
128506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
1293a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			iflag = 1;
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
1296a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			qflag = 1;
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
1299a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			rflag = 1;
1300a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			/* fall through to tflag++ */
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
1305a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			Tflag = 1;
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
13108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
13118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
13128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
13179c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
132017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
132117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
132217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
1325102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1326102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				error_msg_and_die("Bad column width '%s'", optarg);
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1338e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			process_opt_p_list(optarg);
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
13408a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
13418a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
13428a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1343cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
13448a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
13458a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1348dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1349b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1350dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1358de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
13591d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
13601d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1361de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
1362b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		case 'I':
1363b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = atoi(optarg);
1364b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1365b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1366b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			}
1367b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			break;
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1373837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1374837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1376102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1377102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
13781d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1379102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1380102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1381102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1382837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1383fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (!argv[0] == !nprocs)
1384ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1385ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1386fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 && daemonized_tracer) {
1387cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1388d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1389d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
139006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
139106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
139206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1393cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1394cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1395cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1396cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1402cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
14045d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
14055d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1406cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
141704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
14183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
141931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	test_ptrace_seize();
14208044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
142337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
142437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
142537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
142637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
142737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
142837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
14297dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
14307dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
14317dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
143254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
14333d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
14343d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
1435328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko	} else {
1436328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		/* -ff without -o FILE is the same as single -f */
1437328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		if (followfork > 1)
1438328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko			followfork = 1;
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1441cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1442a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1443a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1444a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1446cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1447837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
1448b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (!opt_intr)
1449b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = INTR_NEVER;
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1451369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1452b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (!opt_intr)
1453b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		opt_intr = INTR_WHILE_WAIT;
1454b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
1455b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	/* argv[0]	-pPID	-oFILE	Default interactive setting
1456b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	0	INTR_WHILE_WAIT
1457b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	0	INTR_WHILE_WAIT
1458b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	1	INTR_NEVER
1459b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	1	INTR_WHILE_WAIT
146054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
146154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
146254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
146354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
146454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
146554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
146661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	if (argv[0]) {
146761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		skip_startup_execve = 1;
1468837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
146961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	}
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
1476b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1477b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1478b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (opt_intr != INTR_ANYWHERE) {
1479b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_BLOCK_TSTP_TOO)
1480b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1481b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/*
1482b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1483b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * fatal signals are blocked while syscall stop is processed,
1484b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * and acted on in between, when waiting for new syscall stops.
1485b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In non-interactive mode, signals are ignored.
1486b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 */
1487b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_WHILE_WAIT) {
1488b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGHUP);
1489b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGINT);
1490b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGQUIT);
1491b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGPIPE);
1492b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGTERM);
1493b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_handler = interrupt;
1494b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		}
1495b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/* SIG_IGN, or set handler for these */
1496b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGHUP, &sa, NULL);
1497b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGINT, &sa, NULL);
1498b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGQUIT, &sa, NULL);
1499b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGPIPE, &sa, NULL);
1500b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGTERM, &sa, NULL);
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1502fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 || daemonized_tracer)
150302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
150402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1505fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	/* Do we want pids printed in our -o OUTFILE?
1506fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -ff: no (every pid has its own file); or
1507fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -f: yes (there can be more pids in the future); or
1508fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -p PID1,PID2: yes (there are already more than one pid)
1509fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 */
1510fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15132b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1514418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
15157b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
15167b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
15177b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
15187b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
15197b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
15207b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
152118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
152218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
152318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
15241d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!newtab || !newtcbs)
15251d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
15267b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
15277b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
152818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
152918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
15307b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
15317b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
153310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1538418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1539418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1540418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1541ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1542ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
154418da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1546381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko			tcp->flags = TCB_INUSE;
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1548a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#if SUPPORTED_PERSONALITIES > 1
1549a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin			tcp->currpers = current_personality;
1550a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#endif
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
1552a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
15531d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
155410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
155510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
155918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1562eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
156354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
156654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
156754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
156854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1570ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
157154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
157254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15801201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
158419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
1586a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko	if (debug_flag)
15871d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1588eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
15893e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko	if (tcp->outf) {
15903e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko		if (outfname && followfork >= 2) {
15913e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			if (tcp->curcol != 0)
15923e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko				fprintf(tcp->outf, " <detached ...>\n");
15933e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			fclose(tcp->outf);
15943e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			if (outf == tcp->outf)
15953e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko				outf = NULL;
15963e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko		} else {
15973e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			if (printing_tcp == tcp && tcp->curcol != 0)
15983e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko				fprintf(tcp->outf, " <detached ...>\n");
15993e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko			fflush(tcp->outf);
16003e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko		}
16013e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko	}
16023e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko
16037de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (printing_tcp == tcp)
16047de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		printing_tcp = NULL;
16057de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
160619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16090a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
161075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * Never call DETACH twice on the same process as both unattached and
161175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * attached-unstopped processes give the same ESRCH.  For unattached process we
161275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko * would SIGSTOP it and wait for its SIGSTOP notification forever.
161375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko */
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16154c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkodetach(struct tcb *tcp)
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
161775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int error;
161875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int status, sigstop_expected;
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1621840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16257bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16267bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16287bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16307bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16317bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
163275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
16333e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko	error = 0;
163475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	sigstop_expected = 0;
163575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (tcp->flags & TCB_ATTACHED) {
163675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		/*
163775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * We attached but possibly didn't see the expected SIGSTOP.
163875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * We must catch exactly one as otherwise the detached process
163975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 * would be left stopped (process state T).
164075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		 */
164175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
164275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
164375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (error == 0) {
164475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			/* On a clear day, you can see forever. */
164575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
164675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (errno != ESRCH) {
164775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			/* Shouldn't happen. */
164875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			perror("detach: ptrace(PTRACE_DETACH, ...)");
164975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
165075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (my_tkill(tcp->pid, 0) < 0) {
165175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			if (errno != ESRCH)
165275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				perror("detach: checking sanity");
165375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
165475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
165575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			if (errno != ESRCH)
165675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				perror("detach: stopping child");
165775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		}
165875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		else
165975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			sigstop_expected = 1;
16607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
166175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
166275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (sigstop_expected) {
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
16647508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
166537ab4b79de57c1657e41f96a96fa699a08194a80Denys Vlasenko			if (waitpid(tcp->pid, &status, __WALL) < 0) {
16667508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16677508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16687508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16707508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16717508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16727508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16737508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16747508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16757508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16767508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16777508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16787508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16797508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
16807508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
168137ab4b79de57c1657e41f96a96fa699a08194a80Denys Vlasenko					if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
16827508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16837508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16847508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16857508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16867508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16877508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16887508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16907508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
16964c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, 0);
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1699732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
170075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1701732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1702732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1705ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	if (!qflag && (tcp->flags & TCB_ATTACHED))
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1711a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17161201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
17203521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	int fatal_sig;
17213521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko
17223521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	/* 'interrupted' is a volatile object, fetch it only once */
17233521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	fatal_sig = interrupted;
17243521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	if (!fatal_sig)
17253521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko		fatal_sig = SIGTERM;
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1727ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1728ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
1731a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
17347de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (tcp->flags & TCB_STRACE_CHILD) {
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
1736a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko			kill(tcp->pid, fatal_sig);
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17387de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		detach(tcp);
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17451201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
1747a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko	interrupted = sig;
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
17511201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
175426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
175526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
1756eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
175726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1759eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
1760f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int pid;
1761f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int wait_errno;
1762f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int status, sig;
176331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int stopped;
1764f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		struct tcb *tcp;
1765f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		unsigned event;
1766f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1767222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
1768eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
1769eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1770eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
177126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
177226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
17735bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
17742f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
17752f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
177626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
17772f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
17785bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
17792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
178026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
178126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
1782cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
17832f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
17842f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
178526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
178626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
178726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
1789eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1790eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
1793eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
1794eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1796eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
1803eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
1804eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
1805eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
18064c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("wait");
1807eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
181010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
181110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
18127dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
181310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
181410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
1815f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1816f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		event = ((unsigned)status >> 16);
1817a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag) {
18181d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
181967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
18201d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
18211d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
18221d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
18231d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
18241d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
18251d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18261d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
18271d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
18281d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18291d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
18301d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
18311d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
18321d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
18331d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
18345bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
18351d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
18361d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
18375bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
183867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			evbuf[0] = '\0';
183967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			if (event != 0) {
184067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				static const char *const event_names[] = {
184167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
184267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
184367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
184467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
184567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
184667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
184767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				};
184867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				const char *e;
184967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				if (event < ARRAY_SIZE(event_names))
185067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = event_names[event];
185167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				else {
185267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					sprintf(buf, "?? (%u)", event);
185367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = buf;
185467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				}
185567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				sprintf(evbuf, ",PTRACE_EVENT_%s", e);
185667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			}
185767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
18581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1860f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Look up 'pid' in our table. */
18615d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
1862f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1863f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Under Linux, execve changes pid to thread leader's pid,
1864f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and we see this changed pid on EVENT_EXEC and later,
1865f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * execve sysexit. Leader "disappears" without exit
1866f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * notification. Let user know that, drop leader's tcb,
1867f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and fix up pid in execve thread's tcb.
1868f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * Effectively, execve thread's tcb replaces leader's tcb.
1869f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1870f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1871f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * on exit syscall) in multithreaded programs exactly
1872f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * in order to handle this case.
1873f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1874f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1875f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * On 2.6 and earlier, it can return garbage.
1876f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 */
18776e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
1878f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			long old_pid = 0;
1879f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1880f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid > 0
1881f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid != pid
1882f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			) {
1883f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				struct tcb *execve_thread = pid2tcb(old_pid);
1884f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
1885f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					outf = tcp->outf;
1886f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					curcol = tcp->curcol;
1887f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					if (execve_thread) {
18887de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						if (execve_thread->curcol != 0) {
18897de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							/*
18907de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							 * One case we are here is -ff:
18917de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							 * try "strace -oLOG -ff test/threaded_execve"
18927de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							 */
18937de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
18947de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko							execve_thread->curcol = 0;
18957de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						}
1896f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						/* swap output FILEs (needed for -ff) */
1897f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						tcp->outf = execve_thread->outf;
18987de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						tcp->curcol = execve_thread->curcol;
1899f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						execve_thread->outf = outf;
19007de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						execve_thread->curcol = curcol;
1901f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					}
1902f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					droptcb(tcp);
1903f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
1904f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				tcp = execve_thread;
1905f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
1906f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->pid = pid;
1907f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->flags |= TCB_REPRINT;
19087de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko					if (!cflag) {
19097de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						printleader(tcp);
19107de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
19117de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko						line_ended();
19127de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko					}
1913f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
1914f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			}
1915f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		}
1916f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
191761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
191861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			if (!skip_startup_execve)
191961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko				detach(tcp);
192061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			/* This was initial execve for "strace PROG". Skip. */
192161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			skip_startup_execve = 0;
192261e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		}
192361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
19245d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
192541c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
1926e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
1927e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
1928e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
1929e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
1930e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
1931e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
1932e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
1933e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
1934e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
1935418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
193631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
1937e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
1938833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
1939e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
19408b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
1941e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
1942e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
1943e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
1944e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
1945e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
194697c503fa2e9cd02126feae659f133631c8eb36f1Denys Vlasenko					ptrace(PTRACE_CONT, pid, (char *) 0, 0);
1947cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
1948e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19507de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
19517de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		/* Set current output file */
1952eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
1953ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
19547de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
195513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1959eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
1961a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
1962a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
1963e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
196613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
1967000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s %s+++\n",
19682efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
196913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
197013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
1971000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s +++\n",
197213d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
19732efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
19747de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
1980a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
1981a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
198219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
198319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
1984000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
19857de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
198619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1996f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
1997f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
1998a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
1999f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
200102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
200302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
20042ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
20066cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
20076cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
2014a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko				if (debug_flag)
201544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
201644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
201744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
201844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
201944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
20203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
20213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
20223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2023f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2024f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
202531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		sig = WSTOPSIG(status);
202631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
2027f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event != 0) {
202831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Ptrace event */
202931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
203031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
20316703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				/*
20326703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop or group-stop.
20336703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
20346703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 */
203531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (sig == SIGSTOP
203631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTSTP
203731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTIN
203831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTOU
203931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				) {
204031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					stopped = 1;
204131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					goto show_stopsig;
204231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
204331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
204431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
2045f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2046f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2047f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2048f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2049f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2050f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2051f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2052f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2053f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2054f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2055a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2056f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2057f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
20586cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20616cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
206231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			siginfo_t si;
206331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
206431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Nonzero (true) if tracee is stopped by signal
206531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * (as opposed to "tracee received signal").
206631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
206731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
20686703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#ifdef USE_SEIZE
206931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig:
20706703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif
2071e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
20726cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2073c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
20746b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
20756b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
20767b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2077932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2078932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
20797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
20806b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
20817b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
20826b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
20832ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
20846b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
20852ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
20862ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
20877b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
208931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!stopped) {
20902c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf("--- %s ", signame(sig));
20916b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
20922c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf(PC_FORMAT_STR " ---\n"
20936b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
20946b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
20952c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
20966cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
20976b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
20987de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
210031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
210131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!stopped)
210231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* It's signal-delivery-stop. Inject the signal */
210331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				goto restart_tracee;
210431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
210531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* It's group-stop */
210631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
210731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (use_seize) {
210831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/*
210931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This ends ptrace-stop, but does *not* end group-stop.
211031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This makes stopping signals work properly on straced process
211131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * (that is, process really stops. It used to continue to run).
211231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 */
211331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
211431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cleanup();
211531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					return -1;
211631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
21177de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				tcp->curcol = curcol;
211831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
211931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
212031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* We don't have PTRACE_LISTEN support... */
212131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
21226cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21242ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
21252ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
212602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
212702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
21282ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
21292ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
21302ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
21312ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
21322ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2133eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2134eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2135eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2136eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2137f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
21387de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * We assume that ptrace error was caused by process death.
2139f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * We used to detach(tcp) here, but since we no longer
2140f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * implement "detach before death" policy/hack,
2141f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * we can let this process to report its death to us
2142f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * normally, via WIFEXITED or WIFSIGNALED wait status.
2143f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 */
21447de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			tcp->curcol = curcol;
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21476cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
21486cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
21496cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2150ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2151ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
21526cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
2159ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2160ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoint
2161ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkomain(int argc, char *argv[])
2162ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko{
2163ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	init(argc, argv);
2164ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2165ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	/* Run main tracing loop */
2166ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (trace() < 0)
2167ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		return 1;
2168ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2169ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	cleanup();
2170ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	fflush(NULL);
2171ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (exit_code > 0xff) {
2172ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Avoid potential core file clobbering.  */
2173ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		struct rlimit rlim = {0, 0};
2174ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		setrlimit(RLIMIT_CORE, &rlim);
2175ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2176ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Child was killed by a signal, mimic that.  */
2177ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code &= 0xff;
2178ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		signal(exit_code, SIG_DFL);
2179ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		raise(exit_code);
2180ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Paranoia - what if this signal is not fatal?
2181ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		   Exit with 128 + signo then.  */
2182ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code += 128;
2183ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	}
2184ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2185ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	return exit_code;
2186ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko}
2187