strace.c revision 6e4f3c1fa41851cb72230432db4be8e0c2993c7d
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
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h>
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
41f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#include <sys/utsname.h>
428470374cba7df0e70653d95c4f336a4082c68d82Denys Vlasenko#if defined(IA64)
437b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
447b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
45a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko/* In some libc, these aren't declared. Do it ourself: */
4696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
47418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
48418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
4996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
50a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
51a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#if defined __NR_tkill
52a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
53a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#else
54a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko   /* kill() may choose arbitrarily the target task of the process group
55a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko      while we later wait on a that specific TID.  PID process waits become
56a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko      TID task specific waits for a process under ptrace(2).  */
57a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
58a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) kill((tid), (sig))
59a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#endif
60a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
61a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#undef KERNEL_VERSION
62a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
63a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
64a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkocflag_t cflag = CFLAG_NONE;
65a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int followfork = 0;
66f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
67a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int xflag = 0;
68a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool debug_flag = 0;
69a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool Tflag = 0;
70a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool qflag = 0;
713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
7275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
73a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic unsigned int tflag = 0;
74a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool iflag = 0;
75a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool rflag = 0;
76a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool print_pid_pfx = 0;
77b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
78b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* -I n */
79b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkoenum {
80b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NOT_SET        = 0,
81b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_ANYWHERE       = 1, /* don't block/ignore any signals */
82b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_WHILE_WAIT     = 2, /* block fatal signals while decoding syscall. default */
83b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NEVER          = 3, /* block fatal signals. default if '-o FILE PROG' */
84b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    NUM_INTR_OPTS
86b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko};
87b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkostatic int opt_intr;
88b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* We play with signal mask only if this mode is active: */
89b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#define interactive (opt_intr == INTR_WHILE_WAIT)
90b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
10631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
10731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize (post_attach_sigstop == 0)
10831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
10931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
11031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize 0
11131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
11231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
11317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
114a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool not_failing_only = 0;
11517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
117a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool show_fd_path = 0;
1188a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1198a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
120a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool tracing_paths = 0;
1218a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
12261e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool detach_on_execve = 0;
12361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool skip_startup_execve = 0;
12461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
125a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
126a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
12775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
128eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
129b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
130ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
131ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int max_strlen = DEFAULT_STRLEN;
134ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstatic int acolumn = DEFAULT_ACOLUMN;
135102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
1366764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko
137b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
1386764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko/* If -ff, points to stderr. Else, it's our common output log */
1396764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenkostatic FILE *shared_log;
1406764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko
141000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenkostruct tcb *printing_tcp = NULL;
1426764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenkostatic struct tcb *current_tcp;
1436764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko
144ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1452b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
146ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1486e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned os_release; /* generated from uname()'s u.release */
149f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1504c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp);
151e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
152e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
153e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
158a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#else
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
160a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#endif
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1622c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#ifndef HAVE_STRERROR
1632c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1642c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#if !HAVE_DECL_SYS_ERRLIST
1652c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern int sys_nerr;
1662c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern char *sys_errlist[];
167a6d91ded3f2d5401e09a9c2fa442aabfbfe593a8Denys Vlasenko#endif
1682c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1692c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoconst char *
1702c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkostrerror(int err_no)
1712c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko{
1722c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
1732c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1742c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
1752c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
1762c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko		return buf;
1772c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	}
1782c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	return sys_errlist[err_no];
1792c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko}
1802c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1812c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#endif /* HAVE_STERRROR */
1822c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
184cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
187c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenkousage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\
188c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko              [-a column] [-o file] [-s strsize] [-P path]...\n\
189c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
190c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   or: strace -c[df] [-I n] [-e expr]... [-O overhead] [-S sortby]\n\
191c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
193c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-C -- like -c but also print regular output\n\
1943e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-d -- enable debug output to stderr\n\
195b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
1973e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-F -- attempt to follow vforks (deprecated, use -f)\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
201cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-T -- print time spent in each syscall\n\
202cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
2048a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
205c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-h -- print help message, -V -- print version\n\
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
209c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-I interruptible --\n\
210c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   1: no signals are blocked\n\
211c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   2: fatal signals are blocked while decoding syscall (default)\n\
212c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   3: fatal signals are always blocked (default if '-o FILE PROG')\n\
213c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   4: fatal signals and SIGTSTP (^Z) are always blocked\n\
214c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko      (useful to make 'strace -o FILE PROG' not stop on ^Z)\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
317ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstatic void
318ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinerror_opt_arg(int opt, const char *arg)
319ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin{
320ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	error_msg_and_die("Invalid -%c argument: '%s'", opt, arg);
321ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin}
322ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin
323c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
324c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
325c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
326c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
327c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
328c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
329c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
330c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
33131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
33231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int
33331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid)
33431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
33531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int r;
33631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (!use_seize)
33731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return ptrace(PTRACE_ATTACH, pid, 0, 0);
33831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
33931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (r)
34031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return r;
34131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
34231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	return r;
34331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
34431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
34531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
34631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
34731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
348852f98a3824f6b8359df744af5772306410341abDenys Vlasenko/*
349852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Used when we want to unblock stopped traced process.
350852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
351852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Returns 0 on success or if error was ESRCH
352852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * (presumably process was killed while we talk to it).
353852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Otherwise prints error message and returns -1.
354852f98a3824f6b8359df744af5772306410341abDenys Vlasenko */
355852f98a3824f6b8359df744af5772306410341abDenys Vlasenkostatic int
356852f98a3824f6b8359df744af5772306410341abDenys Vlasenkoptrace_restart(int op, struct tcb *tcp, int sig)
357852f98a3824f6b8359df744af5772306410341abDenys Vlasenko{
358852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	int err;
359852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	const char *msg;
360852f98a3824f6b8359df744af5772306410341abDenys Vlasenko
361852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	errno = 0;
362852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	ptrace(op, tcp->pid, (void *) 0, (long) sig);
363852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	err = errno;
364235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	if (!err)
365852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		return 0;
366852f98a3824f6b8359df744af5772306410341abDenys Vlasenko
367852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	msg = "SYSCALL";
368852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	if (op == PTRACE_CONT)
369852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		msg = "CONT";
370852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	if (op == PTRACE_DETACH)
371852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		msg = "DETACH";
372852f98a3824f6b8359df744af5772306410341abDenys Vlasenko#ifdef PTRACE_LISTEN
373852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	if (op == PTRACE_LISTEN)
374852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		msg = "LISTEN";
375852f98a3824f6b8359df744af5772306410341abDenys Vlasenko#endif
376235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	/*
377235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * Why curcol != 0? Otherwise sometimes we get this:
378235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 *
379235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * 10252 kill(10253, SIGKILL)              = 0
380235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 *  <ptrace(SYSCALL,10252):No such process>10253 ...next decode...
381235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 *
382235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * 10252 died after we retrieved syscall exit data,
383235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * but before we tried to restart it. Log looks ugly.
384235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 */
3856764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp && current_tcp->curcol != 0) {
386235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		tprintf(" <ptrace(%s):%s>\n", msg, strerror(err));
387235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		line_ended();
388235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	}
389235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	if (err == ESRCH)
390235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		return 0;
391235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	errno = err;
392852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
393852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	return -1;
394852f98a3824f6b8359df744af5772306410341abDenys Vlasenko}
395852f98a3824f6b8359df744af5772306410341abDenys Vlasenko
3961f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3991f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
4001f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
4011f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
4021f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
4031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
4041f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
4051f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
4061f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
4071f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
4081f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
40910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
41010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
41110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
41210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
4131f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
41410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4151f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
41610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
41875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenkostatic void kill_save_errno(pid_t pid, int sig)
41975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko{
42075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int saved_errno = errno;
42175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
42275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	(void) kill(pid, sig);
42375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	errno = saved_errno;
42475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko}
42575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
426800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/*
427800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * When strace is setuid executable, we have to swap uids
428800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * before and after filesystem and process management operations.
429800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */
430800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void
431800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkoswap_uid(void)
432800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
433800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int euid = geteuid(), uid = getuid();
434800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
435800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
436800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("setreuid");
437800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
438800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
439800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
440800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if _LFS64_LARGEFILE
441800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define fopen_for_output fopen64
442800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#else
443800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define fopen_for_output fopen
444800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
445800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
446800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic FILE *
447800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostrace_fopen(const char *path)
448800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
449800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	FILE *fp;
450800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
451800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
452800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	fp = fopen_for_output(path, "w");
453800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (!fp)
454800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
455800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
456800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	set_cloexec_flag(fileno(fp));
457800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	return fp;
458800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
459800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
460800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic int popen_pid = 0;
461800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
462800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifndef _PATH_BSHELL
463800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define _PATH_BSHELL "/bin/sh"
464800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
465800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
466800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/*
467800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * We cannot use standard popen(3) here because we have to distinguish
468800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * popen child process from other processes we trace, and standard popen(3)
469800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * does not export its child's pid.
470800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */
471800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic FILE *
472800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostrace_popen(const char *command)
473800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
474800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	FILE *fp;
475800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int fds[2];
476800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
477800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
478800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (pipe(fds) < 0)
479800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("pipe");
480800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
481800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
482800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
483800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	popen_pid = vfork();
484800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (popen_pid == -1)
485800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("vfork");
486800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
487800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (popen_pid == 0) {
488800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		/* child */
489800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		close(fds[1]);
490800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		if (fds[0] != 0) {
491800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (dup2(fds[0], 0))
492800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				perror_msg_and_die("dup2");
493800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			close(fds[0]);
494800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
495800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
496800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
497800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
498800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
499800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	/* parent */
500800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	close(fds[0]);
501800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
502800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	fp = fdopen(fds[1], "w");
503800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (!fp)
504800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		die_out_of_memory();
505800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	return fp;
506800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
507800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
5082e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
5092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprintf(const char *fmt, ...)
5102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
5112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_list args;
5122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_start(args, fmt);
5146764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp) {
5156e4f3c1fa41851cb72230432db4be8e0c2993c7dDenys Vlasenko		int n = strace_vfprintf(current_tcp->outf, fmt, args);
5162e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n < 0) {
5176764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			if (current_tcp->outf != stderr)
5182e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				perror(outfname == NULL
5192e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				       ? "<writing to pipe>" : outfname);
5202e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		} else
5216764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			current_tcp->curcol += n;
5222e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
5232e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_end(args);
5242e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
5252e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5262e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
5272e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprints(const char *str)
5282e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
5296764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp) {
530142aee0a593ea9b42aa98347d998176b8a4e2489Denys Vlasenko		int n = fputs_unlocked(str, current_tcp->outf);
5312e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n >= 0) {
5326764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			current_tcp->curcol += strlen(str);
5332e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			return;
5342e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
5356764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		if (current_tcp->outf != stderr)
5366764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			perror(!outfname ? "<writing to pipe>" : outfname);
5372e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
5382e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
5392e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5402e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
5417de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkoline_ended(void)
5427de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko{
5436764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp) {
5446764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		current_tcp->curcol = 0;
5456764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		fflush(current_tcp->outf);
5466764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	}
5476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (printing_tcp) {
5486764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		printing_tcp->curcol = 0;
5496764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		printing_tcp = NULL;
5506764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	}
5517de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko}
5527de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
5537de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenkovoid
5542e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkoprintleader(struct tcb *tcp)
5552e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
5567de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	/* If -ff, "previous tcb we printed" is always the same as current,
5577de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	 * because we have per-tcb output files.
5587de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	 */
5597de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko	if (followfork >= 2)
5607de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		printing_tcp = tcp;
5617de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
5622e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (printing_tcp) {
5636764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		current_tcp = printing_tcp;
5647de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (printing_tcp->curcol != 0 && (followfork < 2 || printing_tcp == tcp)) {
5657de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			/*
5667de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * case 1: we have a shared log (i.e. not -ff), and last line
5677de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * wasn't finished (same or different tcb, doesn't matter).
5687de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * case 2: split log, we are the same tcb, but our last line
5697de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * didn't finish ("SIGKILL nuked us after syscall entry" etc).
5707de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 */
5712e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprints(" <unfinished ...>\n");
5727de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			printing_tcp->curcol = 0;
5732e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
5742e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
5752e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5762e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	printing_tcp = tcp;
5776764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	current_tcp = tcp;
5786764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	current_tcp->curcol = 0;
5792e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5802e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (print_pid_pfx)
5812e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("%-5d ", tcp->pid);
5822e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	else if (nprocs > 1 && !outfname)
5832e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		tprintf("[pid %5u] ", tcp->pid);
5842e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5852e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (tflag) {
5862e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		char str[sizeof("HH:MM:SS")];
5872e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		struct timeval tv, dtv;
5882e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		static struct timeval otv;
5892e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5902e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		gettimeofday(&tv, NULL);
5912e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (rflag) {
5922e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (otv.tv_sec == 0)
5932e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				otv = tv;
5942e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tv_sub(&dtv, &tv, &otv);
5952e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%6ld.%06ld ",
5962e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) dtv.tv_sec, (long) dtv.tv_usec);
5972e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			otv = tv;
5982e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
5992e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else if (tflag > 2) {
6002e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			tprintf("%ld.%06ld ",
6012e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				(long) tv.tv_sec, (long) tv.tv_usec);
6022e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
6032e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		else {
6042e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			time_t local = tv.tv_sec;
6052e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			strftime(str, sizeof(str), "%T", localtime(&local));
6062e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			if (tflag > 1)
6072e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
6082e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko			else
6092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko				tprintf("%s ", str);
6102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		}
6112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	}
6122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	if (iflag)
6132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		printcall(tcp);
6142e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
6152e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
6162e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
6172e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotabto(void)
6182e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
6196764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp->curcol < acolumn)
6206764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		tprints(acolumn_spaces + current_tcp->curcol);
6212e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko}
6222e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
6233db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko/* Should be only called directly *after successful attach* to a tracee.
6243db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko * Otherwise, "strace -oFILE -ff -p<nonexistant_pid>"
6253db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko * may create bogus empty FILE.<nonexistant_pid>, and then die.
6263db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko */
62710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
628800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkonewoutf(struct tcb *tcp)
62910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
6306764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	tcp->outf = shared_log; /* if not -ff mode, the same file is for all */
6313db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko	if (followfork >= 2) {
632800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		char name[520 + sizeof(int) * 3];
633800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
634800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		tcp->outf = strace_fopen(name);
63510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
63610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
63710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
638800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void
639800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkoexpand_tcbtab(void)
640800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
641800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	/* Allocate some more TCBs and expand the table.
642800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	   We don't want to relocate the TCBs because our
643800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	   callers have pointers and it would be a pain.
644800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	   So tcbtab is a table of pointers.  Since we never
645800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	   free the TCBs, we allocate a single chunk of many.  */
646800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int i = tcbtabsize;
647800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
648800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
649800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (!newtab || !newtcbs)
650800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		die_out_of_memory();
651800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	tcbtabsize *= 2;
652800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	tcbtab = newtab;
653800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	while (i < tcbtabsize)
654800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		tcbtab[i++] = newtcbs++;
655800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
6564bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
657800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic struct tcb *
6583db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenkoalloctcb(int pid)
65910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
660800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int i;
661800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	struct tcb *tcp;
66210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
663800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (nprocs == tcbtabsize)
664800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		expand_tcbtab();
665800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
666800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	for (i = 0; i < tcbtabsize; i++) {
667800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		tcp = tcbtab[i];
668800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		if ((tcp->flags & TCB_INUSE) == 0) {
669800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
670800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			tcp->pid = pid;
671800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			tcp->flags = TCB_INUSE;
672800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if SUPPORTED_PERSONALITIES > 1
673800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			tcp->currpers = current_personality;
674800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
675800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			nprocs++;
676800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (debug_flag)
677800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
678800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			return tcp;
679800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
680800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
6813db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko	error_msg_and_die("bug in alloctcb");
68210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
68310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
684800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void
685800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkodroptcb(struct tcb *tcp)
686800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
687800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (tcp->pid == 0)
688800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		return;
68910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
690800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	nprocs--;
691800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (debug_flag)
692800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
69310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
694800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (tcp->outf) {
6958511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko		if (followfork >= 2) {
696800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (tcp->curcol != 0)
697800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				fprintf(tcp->outf, " <detached ...>\n");
698800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			fclose(tcp->outf);
699800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		} else {
700800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (printing_tcp == tcp && tcp->curcol != 0)
701800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				fprintf(tcp->outf, " <detached ...>\n");
702800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			fflush(tcp->outf);
703800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
704800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
705800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
7066764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp == tcp)
7076764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		current_tcp = NULL;
708800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (printing_tcp == tcp)
709800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		printing_tcp = NULL;
710800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
711800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	memset(tcp, 0, sizeof(*tcp));
712800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
713800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
714800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/* detach traced process; continue with sig
715800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * Never call DETACH twice on the same process as both unattached and
716800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * attached-unstopped processes give the same ESRCH.  For unattached process we
717800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * would SIGSTOP it and wait for its SIGSTOP notification forever.
71810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
719800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic int
720800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkodetach(struct tcb *tcp)
72110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
722800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int error;
723800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int status, sigstop_expected;
72410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
725800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (tcp->flags & TCB_BPTSET)
726800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		clearbpt(tcp);
72710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
728800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	/*
729800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	 * Linux wrongly insists the child be stopped
730800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	 * before detaching.  Arghh.  We go through hoops
731800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	 * to make a clean break of things.
732800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	 */
733800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if defined(SPARC)
734800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#undef PTRACE_DETACH
735800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#define PTRACE_DETACH PTRACE_SUNDETACH
736800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
73710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
738800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	error = 0;
739800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	sigstop_expected = 0;
740800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (tcp->flags & TCB_ATTACHED) {
741800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		/*
742800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		 * We attached but possibly didn't see the expected SIGSTOP.
743800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		 * We must catch exactly one as otherwise the detached process
744800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		 * would be left stopped (process state T).
745800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		 */
746800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
747800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
748800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		if (error == 0) {
749800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			/* On a clear day, you can see forever. */
750800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
751800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		else if (errno != ESRCH) {
752800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			/* Shouldn't happen. */
753800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			perror("detach: ptrace(PTRACE_DETACH, ...)");
754800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
755800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		else if (my_tkill(tcp->pid, 0) < 0) {
756800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (errno != ESRCH)
757800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				perror("detach: checking sanity");
758800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
759800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
760800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (errno != ESRCH)
761800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				perror("detach: stopping child");
762800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
763800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		else
764800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			sigstop_expected = 1;
765800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
76610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
767800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (sigstop_expected) {
768800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		for (;;) {
769800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifdef __WALL
770800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (waitpid(tcp->pid, &status, __WALL) < 0) {
771800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				if (errno == ECHILD) /* Already gone.  */
772800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					break;
773800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				if (errno != EINVAL) {
774800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					perror("detach: waiting");
775800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					break;
776800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				}
777800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif /* __WALL */
778800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				/* No __WALL here.  */
779800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				if (waitpid(tcp->pid, &status, 0) < 0) {
780800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					if (errno != ECHILD) {
781800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko						perror("detach: waiting");
782800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko						break;
783800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					}
784800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifdef __WCLONE
785800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					/* If no processes, try clones.  */
786800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
787800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko						if (errno != ECHILD)
788800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko							perror("detach: waiting");
789800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko						break;
790800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					}
791800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif /* __WCLONE */
792800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				}
793800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifdef __WALL
794800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			}
795800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
796800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (!WIFSTOPPED(status)) {
797800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				/* Au revoir, mon ami. */
798800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				break;
799800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			}
800800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (WSTOPSIG(status) == SIGSTOP) {
801800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, 0);
802800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				break;
803800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			}
804800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
805800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
806800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko					: WSTOPSIG(status));
807800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (error < 0)
808800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				break;
80910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
81010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
8117dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
812800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (!qflag && (tcp->flags & TCB_ATTACHED))
813800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		fprintf(stderr, "Process %u detached\n", tcp->pid);
81410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
815800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	droptcb(tcp);
816800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
817800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	return error;
81810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
81910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
820558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkostatic void
821558e5127fb68a7ab5c5ba6d8e976efd77e396cc2Denys Vlasenkoprocess_opt_p_list(char *opt)
822e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko{
823e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	while (*opt) {
824e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		/*
825e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
826e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 * pidof uses space as delim, pgrep uses newline. :(
827e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		 */
828e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		int pid;
829e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char *delim = opt + strcspn(opt, ", \n\t");
830e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		char c = *delim;
831e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
832e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = '\0';
833ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin		pid = string_to_uint(opt);
834e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid <= 0) {
835ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			error_msg_and_die("Invalid process id: '%s'", opt);
836e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
837e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (pid == strace_tracer_pid) {
838ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			error_msg_and_die("I'm sorry, I can't let you do that, Dave.");
839e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		}
840e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		*delim = c;
8413db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		alloctcb(pid);
842e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		if (c == '\0')
843e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			break;
844e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko		opt = delim + 1;
845e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko	}
846e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko}
847e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko
84802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
84902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
85002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
85102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
85202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
85302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
85402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
85502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
85602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
8572e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
858b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
85902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
86002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
86102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
86202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
863ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
864ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
865ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
866014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
867ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
868ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
869ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
87075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
87175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
87275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
873ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
874ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
875ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
876ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
877ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
87875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
87975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
88075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
881ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
882ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
88302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
88402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
88544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
88675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (!(tcp->flags & TCB_INUSE))
88775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue;
88875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
889d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
89075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		if (tcp->flags & TCB_ATTACHED)
89175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			continue; /* no, we already attached it */
892d116a7338645af45090aecc331701e999148d284Denys Vlasenko
893ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
8947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
89502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
89602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
89702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
89802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
89902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
90002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
90102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
902381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
90302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
904381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
905381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
906381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
9077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
90802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
909ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin					/* we trust /proc filesystem */
91002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
91102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
91202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
91302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
91431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (ptrace_attach_or_seize(tid) < 0) {
91502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
916a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko						if (debug_flag)
917f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
918381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
919f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
920a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko					if (debug_flag)
921381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
922381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
923381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
924381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
92531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
9263db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko					newoutf(cur_tcp);
92702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
92802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
929381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
930381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
931381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
932381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
933381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
934381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
9357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
9367a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
93702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
93802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
93902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
94002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
94102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
9427a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
9433db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko? "Process %u attached with %u threads\n"
9443db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko: "Process %u attached\n",
94544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
94602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
94775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				if (!(tcp->flags & TCB_ATTACHED)) {
948f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
949f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
950f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
951f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
952f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
953f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
95402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
9557a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
9567a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
95731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace_attach_or_seize(tcp->pid) < 0) {
95802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
95902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
96002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
96102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
96275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko		tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
9633db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		newoutf(tcp);
964a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
965f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
966ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
967ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
968ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
969ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
970ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
971ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
972ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
973ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
974ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
97502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
97602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
9779c3861d3177f3bfb12b24890fd118bcb77066abbDenys Vlasenko				"Process %u attached\n",
97802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
979f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
98002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
98144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
98202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
98302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
98402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
98502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
98602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
9871201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
98802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
98902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
99002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
99102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
99202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
99302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
99402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
99502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
99602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
99702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
99802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
999cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
100002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
100102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
100202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
100302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
100402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
100502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
100602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
100702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
100802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
100902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
101002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
101102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
101202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
101330145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
101402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
101502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
101602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
10174f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			const char *colon = strchr(path, ':');
10184f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (colon) {
10194f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				n = colon - path;
102002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
102102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
102202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
102302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
102402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
102502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
102602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
102702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
102802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
102902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
103002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
103102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
103202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
103302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
103402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
103502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
103602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
103702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
103802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
103902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
104002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
104102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
104202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
104302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
104402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
104502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
104602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
104702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
1048cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
104902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
1050a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
1051ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
1052cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
1053ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
105475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
105575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
1056ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
1057ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
10586764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		if (shared_log != stderr)
10596764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			close(fileno(shared_log));
106031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!daemonized_tracer && !use_seize) {
106131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
1062cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
1063ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
106402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
106502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1066ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
106702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
106802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
106902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
107002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
107102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
107202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
107302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
107402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
107502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
107602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
107702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
1078ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
1079ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
1080ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
1081ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
1082ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
1083ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
1084ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
1085ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
108602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
108702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
1088ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
108902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
109002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1091ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
1092ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
10932e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
1094ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
10952e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
10962e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
10972e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
1098ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
1099c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
11002e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
1101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
1102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
1103a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko			/* we depend on SIGCHLD set to SIG_DFL by init code */
1104a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko			/* if it happens to be SIG_IGN'ed, wait won't block */
1105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
1106ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
1107ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
110802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
110902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
1110cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
111102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
1112ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
11132e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
111475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
11152e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
111631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!use_seize) {
111731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* child did PTRACE_TRACEME, nothing to do in parent */
111831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		} else {
111931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked) {
112031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* Wait until child stopped itself */
112131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				int status;
112231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				while (waitpid(pid, &status, WSTOPPED) < 0) {
112331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (errno == EINTR)
112431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko						continue;
112531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("waitpid");
112631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
112731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
112875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko					kill_save_errno(pid, SIGKILL);
112931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("Unexpected wait status %x", status);
113031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
113131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
113231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Else: vforked case, we have no way to sync.
113331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * Just attach to it as soon as possible.
113431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * This means that we may miss a few first syscalls...
113531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
113631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
113731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace_attach_or_seize(pid)) {
113875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				kill_save_errno(pid, SIGKILL);
113931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				perror_msg_and_die("Can't attach to %d", pid);
114031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
114131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked)
114231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGCONT);
114331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
11442e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
1145f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
114675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
1147f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
114875fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
11493db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		newoutf(tcp);
11502e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
11512e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
11522e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
11532e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
11542e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
11552e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
1156f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		alloctcb(pid);
1157f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		/* attaching will be done later, by startup_attach */
11583db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		/* note: we don't do newoutf(tcp) here either! */
1159ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
116002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
116102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1162b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
1163b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
1164b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
1165b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
1166b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
116704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
11683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
1169b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
11702fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
11712fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
11722fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
11732fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
1174b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
11755d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
11765d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
117704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
11785d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
117904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
118031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
118104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
118204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
11834c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko		kill_save_errno(pid, SIGSTOP);
118404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
118504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
118604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
1187b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
1188b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
1189b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
1190b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
1191b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
119204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
1193b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
119404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
1195b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
1196b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
11974c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			if (errno == ECHILD)
1198b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
119904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
120004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
120104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
120204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
120304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
120404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
120504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
120604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
120704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
120804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
120904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
121004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
121104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
121204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
121304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
121404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
121504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
121604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
121704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
121804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
121904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
122004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
12214c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			kill_save_errno(pid, SIGKILL);
122204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
122304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
1224b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
1225b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
12262fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
122704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
122804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
122904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
123004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
123104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
123204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
1233b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
123404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
123504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
123604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
123704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
123804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
123904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
124004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
124104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
124204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
12432fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
124404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
124504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
124604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
1247b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
124804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
124904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
125004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
125104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
125204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
1253b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
1254b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
125504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
1256f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1257a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
125804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
125904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
126004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
126104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
126204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
126304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
1264b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
12653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
12663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
12673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
12683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
12693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
12703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
12713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
12723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
12733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
12743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
12753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
12763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
12773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
12783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
12793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
12803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
12813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
12823454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
128304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
128404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
12853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
12863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
12873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
12887ff5ed932568a8049c3ca134da374f64c3e255ceMike Frysinger	/* this fork test doesn't work on no-mmu systems */
12897ff5ed932568a8049c3ca134da374f64c3e255ceMike Frysinger	if (strace_vforked)
12907ff5ed932568a8049c3ca134da374f64c3e255ceMike Frysinger		return;
12917ff5ed932568a8049c3ca134da374f64c3e255ceMike Frysinger
12923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
12933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
129475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
12953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
12963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
12973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
12983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
129975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
130004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
130104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
13023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
13033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
13043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
13053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
13073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
13083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
13103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
13113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
13123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
13133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
131404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
131504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
131604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
131775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
131875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
131975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
132075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
132104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
132204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
132304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
132404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
132504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
132604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
13273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
13293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
133004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
133104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
13323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
13343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
13353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
13363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
13373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
13383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
13393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
134004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
134104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
134204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
13433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
13453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
13463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
134804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
134975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
13503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
13523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
135475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
1355f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1356a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
1357f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1358f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
13593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
13603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
13613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
136204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
136304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
13643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
136531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
136631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# ifdef USE_SEIZE
136731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void
136831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void)
136931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
137031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int pid;
137131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
137231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	pid = fork();
137331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid < 0)
137431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		perror_msg_and_die("fork");
137531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
137631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid == 0) {
137731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		pause();
137831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		_exit(0);
137931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
138031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
138131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	/* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap.  After
138231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * attaching tracee continues to run unless a trap condition occurs.
138331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * PTRACE_SEIZE doesn't affect signal or group stop state.
138431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 */
138531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
138631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
1387a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko	} else if (debug_flag) {
138831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
138931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
139031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
139131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	kill(pid, SIGKILL);
139231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
139331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	while (1) {
139431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int status, tracee_pid;
139531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
139631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		errno = 0;
139731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tracee_pid = waitpid(pid, &status, 0);
139831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (tracee_pid <= 0) {
139931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (errno == EINTR)
140031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
140131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d",
140231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					 __func__, tracee_pid);
140331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
140431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (WIFSIGNALED(status)) {
140531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			return;
140631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
140731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		error_msg_and_die("%s: unexpected wait status %x",
140831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				__func__, status);
140931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
141031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
141131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# else /* !USE_SEIZE */
141231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#  define test_ptrace_seize() ((void)0)
141331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# endif
141431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
14156e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned
1416f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void)
1417f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{
14186e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	unsigned rel;
14196e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	const char *p;
1420f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	struct utsname u;
1421f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (uname(&u) < 0)
1422f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		perror_msg_and_die("uname");
14236e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	/* u.release has this form: "3.2.9[-some-garbage]" */
14246e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	rel = 0;
14256e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	p = u.release;
14266e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	for (;;) {
14276e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (!(*p >= '0' && *p <= '9'))
14286e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
14296e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		/* Note: this open-codes KERNEL_VERSION(): */
14306e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		rel = (rel << 8) | atoi(p);
14316e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (rel >= KERNEL_VERSION(1,0,0))
14326e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			break;
14336e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		while (*p >= '0' && *p <= '9')
14346e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			p++;
14356e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (*p != '.')
14366e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
14376e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		p++;
14386e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	}
14396e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	return rel;
1440f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko}
1441f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1442ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko/*
1443ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Initialization part of main() was eating much stack (~0.5k),
1444ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * which was unused after init.
1445ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * We can reuse it if we move init code into a separate function.
1446ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko *
1447ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Don't want main() to inline us and defeat the reason
1448ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * we have a separate function.
1449ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko */
1450ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void __attribute__ ((noinline))
1451ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoinit(int argc, char *argv[])
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
1454ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	int c, i;
145506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
145908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
1460a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	/* Make sure SIGCHLD has the default action so that waitpid
1461a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   definitely works without losing track of children.  The user
1462a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   should not have given us a bogus state to inherit, but he might
1463a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   have.  Arguably we should detect SIG_IGN here and pass it on
1464a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   to children, but probably noone really needs that.  */
1465a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	signal(SIGCHLD, SIG_DFL);
1466a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko
146775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
146875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
14696e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	os_release = get_os_release();
1470f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1471ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
1472ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
14734f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
14741d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
14751d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
14764f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
14771d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
14781d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
14794f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
14804f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
1481ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
14826764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	shared_log = stderr;
1483138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
1484138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
149061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		"+bcCdfFhiqrtTvVxyz"
1491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1492b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
149461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		case 'b':
149561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			detach_on_execve = 1;
149661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			break;
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1498e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1499c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive");
1500e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1501e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1502e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1503e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1504e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1505c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive");
1506e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1507e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
1510a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			debug_flag = 1;
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1512ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1513ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1514ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
151541c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
151606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
151706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
1525a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			iflag = 1;
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
1528a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			qflag = 1;
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
1531a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			rflag = 1;
1532a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			/* fall through to tflag++ */
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
1537a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			Tflag = 1;
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
15428a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
15438a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
15448a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
15499c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
155217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
155317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
155417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
1556ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			acolumn = string_to_uint(optarg);
1557102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1558ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
1567ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			i = string_to_uint(optarg);
1568ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			if (i < 0)
1569ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
1570ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			set_overhead(i);
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1573e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			process_opt_p_list(optarg);
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
15758a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
15768a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
15778a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1578cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
15798a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
15808a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
1582ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			i = string_to_uint(optarg);
1583ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			if (i < 0)
1584ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
1585ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			max_strlen = i;
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1593de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
15941d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
15951d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1596de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
1597b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		case 'I':
1598ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			opt_intr = string_to_uint(optarg);
1599ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS)
1600ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
1601b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			break;
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1607837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1608837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1610102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1611102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
16121d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1613102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1614102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1615102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1616837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1617fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (!argv[0] == !nprocs)
1618ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1619ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1620fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 && daemonized_tracer) {
1621c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive");
1622d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1623d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
162406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
162506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
162606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
16273db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko	if (followfork >= 2 && cflag) {
1628c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive");
1629cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1630cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1636cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
16385d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
16395d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1640cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
165104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
16523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
165331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	test_ptrace_seize();
16548044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
165737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
165837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
165937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
166037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
166137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
166237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
16633db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko			if (followfork >= 2)
16647dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
16656764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			shared_log = strace_popen(outfname + 1);
166654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
16673db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		else if (followfork < 2)
16686764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			shared_log = strace_fopen(outfname);
1669328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko	} else {
1670328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		/* -ff without -o FILE is the same as single -f */
16713db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		if (followfork >= 2)
1672328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko			followfork = 1;
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1675cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1676a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1677a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1678a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
16796764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
1680cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1681837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
1682b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (!opt_intr)
1683b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = INTR_NEVER;
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1685369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1686b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (!opt_intr)
1687b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		opt_intr = INTR_WHILE_WAIT;
1688b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
1689b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	/* argv[0]	-pPID	-oFILE	Default interactive setting
1690b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	0	INTR_WHILE_WAIT
1691b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	0	INTR_WHILE_WAIT
1692b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	1	INTR_NEVER
1693b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	1	INTR_WHILE_WAIT
169454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
169554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
169654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
169754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
169854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
169954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
170061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	if (argv[0]) {
170161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		skip_startup_execve = 1;
1702837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
170361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	}
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
1710b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1711b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1712b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (opt_intr != INTR_ANYWHERE) {
1713b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_BLOCK_TSTP_TOO)
1714b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1715b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/*
1716b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1717b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * fatal signals are blocked while syscall stop is processed,
1718b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * and acted on in between, when waiting for new syscall stops.
1719b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In non-interactive mode, signals are ignored.
1720b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 */
1721b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_WHILE_WAIT) {
1722b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGHUP);
1723b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGINT);
1724b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGQUIT);
1725b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGPIPE);
1726b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGTERM);
1727b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_handler = interrupt;
1728b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		}
1729b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/* SIG_IGN, or set handler for these */
1730b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGHUP, &sa, NULL);
1731b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGINT, &sa, NULL);
1732b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGQUIT, &sa, NULL);
1733b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGPIPE, &sa, NULL);
1734b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGTERM, &sa, NULL);
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1736fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 || daemonized_tracer)
173702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
173802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1739fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	/* Do we want pids printed in our -o OUTFILE?
1740fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -ff: no (every pid has its own file); or
1741fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -f: yes (there can be more pids in the future); or
1742fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -p PID1,PID2: yes (there are already more than one pid)
1743fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 */
1744fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1747eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
174854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
175154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
175254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
175354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1755ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
175654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
175754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
176054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17651201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
17693521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	int fatal_sig;
17703521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko
17713521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	/* 'interrupted' is a volatile object, fetch it only once */
17723521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	fatal_sig = interrupted;
17733521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	if (!fatal_sig)
17743521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko		fatal_sig = SIGTERM;
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1776ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1777ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
1780a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
17837de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (tcp->flags & TCB_STRACE_CHILD) {
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
1785a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko			kill(tcp->pid, fatal_sig);
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17877de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		detach(tcp);
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
17906764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		call_summary(shared_log);
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17941201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
1796a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko	interrupted = sig;
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18001201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
180326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
180426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
1805eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
180626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1808eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
1809f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int pid;
1810f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int wait_errno;
1811f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int status, sig;
181231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int stopped;
1813f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		struct tcb *tcp;
1814f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		unsigned event;
1815f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1816222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
1817eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
1818eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1819eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
182026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
182126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
18225bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
18232f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
18242f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
182526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
18262f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
18275bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
18282f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
182926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
183026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
1831cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
18322f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
18332f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
183426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
183526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
183626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
1838eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1839eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
1842eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
1843eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1845eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
1852eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
1853eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
1854eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
18554c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("wait");
1856eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
185910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
186010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
18617dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
186210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
186310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
1864f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1865f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		event = ((unsigned)status >> 16);
1866a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag) {
18671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
186867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
18691d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
18701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
18711d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
18721d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
18731d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
18741d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18751d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
18761d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
18771d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
18781d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
18791d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
18801d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
18811d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
18821d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
18835bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
18841d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
18851d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
18865bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
188767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			evbuf[0] = '\0';
188867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			if (event != 0) {
188967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				static const char *const event_names[] = {
189067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
189167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
189267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
189367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
189467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
189567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
189667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				};
189767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				const char *e;
189867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				if (event < ARRAY_SIZE(event_names))
189967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = event_names[event];
190067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				else {
190167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					sprintf(buf, "?? (%u)", event);
190267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = buf;
190367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				}
190467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				sprintf(evbuf, ",PTRACE_EVENT_%s", e);
190567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			}
190667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
19071d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1909f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Look up 'pid' in our table. */
19105d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
1911f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
19128511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko		if (!tcp) {
19138511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (followfork) {
19148511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				/* This is needed to go with the CLONE_PTRACE
19158511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   changes in process.c/util.c: we might see
19168511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   the child's initial trap before we see the
19178511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   parent return from the clone syscall.
19188511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   Leave the child suspended until the parent
19198511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   returns from its system call.  Only then
19208511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   will we have the association of parent and
19218511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   child so that we know how to do clearbpt
19228511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   in the child.  */
19238511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tcp = alloctcb(pid);
19248511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
19258511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				newoutf(tcp);
19268511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				if (!qflag)
19278511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
19288511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko						pid);
19298511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			} else {
19308511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				/* This can happen if a clone call used
19318511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   CLONE_PTRACE itself.  */
19328511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				if (WIFSTOPPED(status))
19338511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko					ptrace(PTRACE_CONT, pid, (char *) 0, 0);
19348511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
19358511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			}
19368511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko		}
19378511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko
1938f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Under Linux, execve changes pid to thread leader's pid,
1939f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and we see this changed pid on EVENT_EXEC and later,
1940f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * execve sysexit. Leader "disappears" without exit
1941f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * notification. Let user know that, drop leader's tcb,
1942f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and fix up pid in execve thread's tcb.
1943f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * Effectively, execve thread's tcb replaces leader's tcb.
1944f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1945f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1946f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * on exit syscall) in multithreaded programs exactly
1947f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * in order to handle this case.
1948f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
1949f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1950f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * On 2.6 and earlier, it can return garbage.
1951f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 */
19526e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
19536764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			FILE *fp;
19548511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			struct tcb *execve_thread;
1955f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			long old_pid = 0;
19568511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko
19578511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
19588511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				goto dont_switch_tcbs;
19598511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (old_pid <= 0 || old_pid == pid)
19608511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				goto dont_switch_tcbs;
19618511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			execve_thread = pid2tcb(old_pid);
19628511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* It should be !NULL, but I feel paranoid */
19638511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (!execve_thread)
19648511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				goto dont_switch_tcbs;
19658511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko
19668511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (execve_thread->curcol != 0) {
19678511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				/*
19688511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				 * One case we are here is -ff:
19698511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				 * try "strace -oLOG -ff test/threaded_execve"
19708511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				 */
19718511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
19726764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko				/*execve_thread->curcol = 0; - no need, see code below */
19738511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			}
19748511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* Swap output FILEs (needed for -ff) */
19756764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			fp = execve_thread->outf;
19766764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			execve_thread->outf = tcp->outf;
19776764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			tcp->outf = fp;
19788511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* And their column positions */
19796764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			execve_thread->curcol = tcp->curcol;
19806764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			tcp->curcol = 0;
19818511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* Drop leader, but close execve'd thread outfile (if -ff) */
19828511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			droptcb(tcp);
19838511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* Switch to the thread, reusing leader's outfile and pid */
19848511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			tcp = execve_thread;
19858511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			tcp->pid = pid;
19868511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (cflag != CFLAG_ONLY_STATS) {
19878511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				printleader(tcp);
19888511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
19898511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				line_ended();
19908511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tcp->flags |= TCB_REPRINT;
1991f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			}
1992f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		}
19938511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko dont_switch_tcbs:
1994f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
199561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
199661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			if (!skip_startup_execve)
199761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko				detach(tcp);
199861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			/* This was initial execve for "strace PROG". Skip. */
199961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			skip_startup_execve = 0;
200061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		}
200161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
20027de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		/* Set current output file */
20036764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		current_tcp = tcp;
20047de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
200513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2009eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2011a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2012a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2013e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
201613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
2017000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s %s+++\n",
20182efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
201913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
202013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
2021000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s +++\n",
202213d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
20232efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
20247de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2030a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2031a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
2032b5e0908a173cc8005ed73fa5c0eab59d03baa7f3Denys Vlasenko			if (cflag != CFLAG_ONLY_STATS) {
203319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
2034000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
20357de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
203619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2046f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
2047f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
2048a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2049f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
205102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
205302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
20542ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
20566cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
20576cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
2064a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko				if (debug_flag)
206544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
206644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
206744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
206844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
206944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
20703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
20713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
20723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2073f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2074f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
207531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		sig = WSTOPSIG(status);
207631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
2077f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event != 0) {
207831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Ptrace event */
207931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
208031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
20816703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				/*
20826703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop or group-stop.
20836703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
20846703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 */
208531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (sig == SIGSTOP
208631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTSTP
208731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTIN
208831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTOU
208931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				) {
209031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					stopped = 1;
209131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					goto show_stopsig;
209231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
209331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
209431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
2095f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2096f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2097f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2098f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2099f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2100f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2101f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2102f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2103f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2104f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2105a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2106f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2107f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
21086cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21116cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
211231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			siginfo_t si;
211331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
211431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Nonzero (true) if tracee is stopped by signal
211531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * (as opposed to "tracee received signal").
2116a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8aDenys Vlasenko			 * TODO: shouldn't we check for errno == EINVAL too?
2117a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8aDenys Vlasenko			 * We can get ESRCH instead, you know...
211831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
211931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
21206703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#ifdef USE_SEIZE
212131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig:
21226703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif
2123e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
21246cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2125c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
21266b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
21276b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
21287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2129932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2130932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
21317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
21326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
21337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
21346b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
21352ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
21366b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
21372ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
21382ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
21397b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
214131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!stopped) {
21422c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf("--- %s ", signame(sig));
21436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
21442c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf(PC_FORMAT_STR " ---\n"
21456b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
21466b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
21472c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
21486cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
21496b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
21507de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
215331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!stopped)
215431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* It's signal-delivery-stop. Inject the signal */
215531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				goto restart_tracee;
215631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
215731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* It's group-stop */
215831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
215931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (use_seize) {
216031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/*
216131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This ends ptrace-stop, but does *not* end group-stop.
216231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This makes stopping signals work properly on straced process
216331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * (that is, process really stops. It used to continue to run).
216431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 */
216531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
216631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cleanup();
216731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					return -1;
216831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
216931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
217031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
217131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* We don't have PTRACE_LISTEN support... */
217231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
21736cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21752ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
21762ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
217702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
217802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
21792ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
21802ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
21812ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
21822ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
21832ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2184235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		if (trace_syscall(tcp) < 0) {
2185235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko			/* ptrace() failed in trace_syscall().
2186eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2187235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko			 * Observed case: exit_group() or SIGKILL terminating
2188f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
21897de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * We assume that ptrace error was caused by process death.
2190f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * We used to detach(tcp) here, but since we no longer
2191f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * implement "detach before death" policy/hack,
2192f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * we can let this process to report its death to us
2193f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * normally, via WIFEXITED or WIFSIGNALED wait status.
2194f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 */
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21976cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
21986cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
21996cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2200ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
22016cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
2208ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2209ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoint
2210ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkomain(int argc, char *argv[])
2211ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko{
2212ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	init(argc, argv);
2213ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2214ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	/* Run main tracing loop */
2215ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (trace() < 0)
2216ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		return 1;
2217ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2218ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	cleanup();
2219ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	fflush(NULL);
2220ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (exit_code > 0xff) {
2221ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Avoid potential core file clobbering.  */
2222ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		struct rlimit rlim = {0, 0};
2223ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		setrlimit(RLIMIT_CORE, &rlim);
2224ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2225ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Child was killed by a signal, mimic that.  */
2226ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code &= 0xff;
2227ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		signal(exit_code, SIG_DFL);
2228ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		raise(exit_code);
2229ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Paranoia - what if this signal is not fatal?
2230ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		   Exit with 128 + signo then.  */
2231ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code += 128;
2232ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	}
2233ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2234ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	return exit_code;
2235ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko}
2236