strace.c revision 05f325199a6cf36c92560d5a08b56652502705c2
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).  */
57978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# warning "tkill(2) not available, risk of strace hangs!"
58a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko# define my_tkill(tid, sig) kill((tid), (sig))
59a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko#endif
60a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko
615c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko/* Glue for systems without a MMU that cannot provide fork() */
625c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if !defined(HAVE_FORK)
635c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko# undef NOMMU_SYSTEM
645c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko# define NOMMU_SYSTEM 1
655c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#endif
665c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if NOMMU_SYSTEM
675c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko# define fork() vfork()
685c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#endif
695c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko
70a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkocflag_t cflag = CFLAG_NONE;
71a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int followfork = 0;
72f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
73a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int xflag = 0;
748d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenkobool need_fork_exec_workarounds = 0;
75a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool debug_flag = 0;
76a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool Tflag = 0;
77a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool qflag = 0;
783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
7975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
80a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic unsigned int tflag = 0;
81a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool iflag = 0;
82a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool rflag = 0;
83a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkostatic bool print_pid_pfx = 0;
84b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
85b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* -I n */
86b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkoenum {
87b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NOT_SET        = 0,
88b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_ANYWHERE       = 1, /* don't block/ignore any signals */
89b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_WHILE_WAIT     = 2, /* block fatal signals while decoding syscall. default */
90b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NEVER          = 3, /* block fatal signals. default if '-o FILE PROG' */
91b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
92b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    NUM_INTR_OPTS
93b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko};
94b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkostatic int opt_intr;
95b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* We play with signal mask only if this mode is active: */
96b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#define interactive (opt_intr == INTR_WHILE_WAIT)
97b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
104ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
106ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
107ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
108ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
109ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
110ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1125c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE
11331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
11431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize (post_attach_sigstop == 0)
11531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
11631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
11731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize 0
11831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
11931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
12017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
121a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool not_failing_only = 0;
12217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1238a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
124a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool show_fd_path = 0;
1258a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1268a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
127a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkobool tracing_paths = 0;
1288a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
12961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool detach_on_execve = 0;
13061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenkostatic bool skip_startup_execve = 0;
13161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
132a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
133a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
13475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
135eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
136b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
137ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
138ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
140a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenkounsigned int max_strlen = DEFAULT_STRLEN;
141ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstatic int acolumn = DEFAULT_ACOLUMN;
142102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
1436764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko
144b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
1456764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko/* If -ff, points to stderr. Else, it's our common output log */
1466764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenkostatic FILE *shared_log;
1476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko
148000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenkostruct tcb *printing_tcp = NULL;
1496764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenkostatic struct tcb *current_tcp;
1506764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko
151ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1522b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
153ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155eec8d5d6b028665a73169fda96e4e873cb8351f0Denys Vlasenkounsigned os_release; /* generated from uname()'s u.release */
156f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1574c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp);
158e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
159e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
160e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
165a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#else
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
167a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#endif
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1692c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#ifndef HAVE_STRERROR
1702c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1712c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#if !HAVE_DECL_SYS_ERRLIST
1722c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern int sys_nerr;
1732c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoextern char *sys_errlist[];
174a6d91ded3f2d5401e09a9c2fa442aabfbfe593a8Denys Vlasenko#endif
1752c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1762c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkoconst char *
1772c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenkostrerror(int err_no)
1782c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko{
1792c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
1802c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1812c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
1822c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
1832c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko		return buf;
1842c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	}
1852c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko	return sys_errlist[err_no];
1862c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko}
1872c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
1882c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko#endif /* HAVE_STERRROR */
1892c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
191cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
194c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenkousage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\
195c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko              [-a column] [-o file] [-s strsize] [-P path]...\n\
196c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
197c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   or: strace -c[df] [-I n] [-e expr]... [-O overhead] [-S sortby]\n\
198c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
200c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-C -- like -c but also print regular output\n\
2013e084ac349c3b177a75916254a4a5a02f29969e2Denys Vlasenko-d -- enable debug output to stderr\n\
202b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
207cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-T -- print time spent in each syscall\n\
208cdab1becb03eeae442719027fc26a17da464e5deDenys Vlasenko-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
2108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
211c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-h -- print help message, -V -- print version\n\
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
21438e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko   options: trace, abbrev, verbose, raw, signal, read, write\n\
215c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko-I interruptible --\n\
216c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   1: no signals are blocked\n\
217c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   2: fatal signals are blocked while decoding syscall (default)\n\
218c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   3: fatal signals are always blocked (default if '-o FILE PROG')\n\
219c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko   4: fatal signals and SIGTSTP (^Z) are always blocked\n\
220c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko      (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
227de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
228de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2298a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
23061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko"
23138e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko/* ancient, no one should use it
23238e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko-F -- attempt to follow vforks (deprecated, use -f)\n\
23338e79bbb25bca8b79ae2866b93c4ddf26dea2b13Denys Vlasenko */
23461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* this is broken, so don't document it
23517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
23661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */
23761e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko/* experimental, don't document it yet (option letter may change in the future!)
23861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko-b -- detach on successful execve\n\
23961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko */
240de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
25682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	char *msg;
25782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
25844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
25982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
26082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We want to print entire message with single fprintf to ensure
26182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * message integrity if stderr is shared with other programs.
26282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * Thus we use vasprintf + single fprintf.
26382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 */
26482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	msg = NULL;
265cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko	if (vasprintf(&msg, fmt, p) >= 0) {
26682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
26782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
26882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
26982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
27082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		free(msg);
27182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	} else {
27282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		/* malloc in vasprintf failed, try it without malloc */
27382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		fprintf(stderr, "%s: ", progname);
27482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		vfprintf(stderr, fmt, p);
27582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
27682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, ": %s\n", strerror(err_no));
27782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
27882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			putc('\n', stderr);
27982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	}
28082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We don't switch stderr to buffered, thus fprintf(stderr)
28182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * always flushes its output and this is not necessary: */
28282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* fflush(stderr); */
28375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
28475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
28575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
28675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
28775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
28875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
28975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
29175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
29375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
29475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
29575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
29675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
29775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
29875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
29975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
30075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
30175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
30275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
30375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
30475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
30575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
30675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
30775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
30875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
30975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
31075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
31175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
31275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
31375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
31475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
3153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
3163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
3171d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
3181d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
3191d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
3201d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
3211d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
3221d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
3231d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
3241d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
3251d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
326ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinstatic void
327ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levinerror_opt_arg(int opt, const char *arg)
328ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin{
329ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	error_msg_and_die("Invalid -%c argument: '%s'", opt, arg);
330ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin}
331ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin
3325c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE
33331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int
33431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid)
33531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
33631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int r;
33731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (!use_seize)
33831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return ptrace(PTRACE_ATTACH, pid, 0, 0);
33926bc0606d96d05d30ba263939a0451889340a64cDenys Vlasenko	r = ptrace(PTRACE_SEIZE, pid, 0, 0);
34031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (r)
34131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return r;
34231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
34331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	return r;
34431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
34531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
34631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
34731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
34831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
349852f98a3824f6b8359df744af5772306410341abDenys Vlasenko/*
350852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Used when we want to unblock stopped traced process.
351852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
352852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Returns 0 on success or if error was ESRCH
353852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * (presumably process was killed while we talk to it).
354852f98a3824f6b8359df744af5772306410341abDenys Vlasenko * Otherwise prints error message and returns -1.
355852f98a3824f6b8359df744af5772306410341abDenys Vlasenko */
356852f98a3824f6b8359df744af5772306410341abDenys Vlasenkostatic int
357852f98a3824f6b8359df744af5772306410341abDenys Vlasenkoptrace_restart(int op, struct tcb *tcp, int sig)
358852f98a3824f6b8359df744af5772306410341abDenys Vlasenko{
359852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	int err;
360852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	const char *msg;
361852f98a3824f6b8359df744af5772306410341abDenys Vlasenko
362852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	errno = 0;
363852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	ptrace(op, tcp->pid, (void *) 0, (long) sig);
364852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	err = errno;
365235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	if (!err)
366852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		return 0;
367852f98a3824f6b8359df744af5772306410341abDenys Vlasenko
368852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	msg = "SYSCALL";
369852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	if (op == PTRACE_CONT)
370852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		msg = "CONT";
371852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	if (op == PTRACE_DETACH)
372852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		msg = "DETACH";
373852f98a3824f6b8359df744af5772306410341abDenys Vlasenko#ifdef PTRACE_LISTEN
374852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	if (op == PTRACE_LISTEN)
375852f98a3824f6b8359df744af5772306410341abDenys Vlasenko		msg = "LISTEN";
376852f98a3824f6b8359df744af5772306410341abDenys Vlasenko#endif
377235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	/*
378235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * Why curcol != 0? Otherwise sometimes we get this:
379235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 *
380235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * 10252 kill(10253, SIGKILL)              = 0
381235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 *  <ptrace(SYSCALL,10252):No such process>10253 ...next decode...
382235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 *
383235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * 10252 died after we retrieved syscall exit data,
384235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 * but before we tried to restart it. Log looks ugly.
385235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	 */
3866764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp && current_tcp->curcol != 0) {
387235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		tprintf(" <ptrace(%s):%s>\n", msg, strerror(err));
388235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		line_ended();
389235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	}
390235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	if (err == ESRCH)
391235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		return 0;
392235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko	errno = err;
393852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	perror_msg("ptrace(PTRACE_%s,pid:%d,sig:%d)", msg, tcp->pid, sig);
394852f98a3824f6b8359df744af5772306410341abDenys Vlasenko	return -1;
395852f98a3824f6b8359df744af5772306410341abDenys Vlasenko}
396852f98a3824f6b8359df744af5772306410341abDenys Vlasenko
3971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
4001f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
4011f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
4021f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
4031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
4041f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
4051f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
4061f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
4071f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
4081f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
4091f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
41010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
41110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
41210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
41310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
4141f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
41510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4161f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
41810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
41975fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenkostatic void kill_save_errno(pid_t pid, int sig)
42075fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko{
42175fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	int saved_errno = errno;
42275fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
42375fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	(void) kill(pid, sig);
42475fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko	errno = saved_errno;
42575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko}
42675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko
427800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/*
428800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * When strace is setuid executable, we have to swap uids
429800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * before and after filesystem and process management operations.
430800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */
431800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic void
432800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkoswap_uid(void)
433800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
434800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int euid = geteuid(), uid = getuid();
435800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
436800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
437800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("setreuid");
438800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
439800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
440800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
441800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#if _LFS64_LARGEFILE
442800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define fopen_for_output fopen64
443800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#else
444800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define fopen_for_output fopen
445800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
446800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
447800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic FILE *
448800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostrace_fopen(const char *path)
449800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
450800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	FILE *fp;
451800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
452800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
453800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	fp = fopen_for_output(path, "w");
454800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (!fp)
455800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
456800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
457800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	set_cloexec_flag(fileno(fp));
458800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	return fp;
459800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
460800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
461800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic int popen_pid = 0;
462800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
463800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#ifndef _PATH_BSHELL
464800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko# define _PATH_BSHELL "/bin/sh"
465800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko#endif
466800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
467800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko/*
468800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * We cannot use standard popen(3) here because we have to distinguish
469800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * popen child process from other processes we trace, and standard popen(3)
470800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko * does not export its child's pid.
471800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko */
472800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostatic FILE *
473800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenkostrace_popen(const char *command)
474800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko{
475800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	FILE *fp;
476800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	int fds[2];
477800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
478800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
479800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (pipe(fds) < 0)
480800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("pipe");
481800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
482800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
483800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
484800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	popen_pid = vfork();
485800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (popen_pid == -1)
486800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("vfork");
487800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
488800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (popen_pid == 0) {
489800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		/* child */
490800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		close(fds[1]);
491800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		if (fds[0] != 0) {
492800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (dup2(fds[0], 0))
493800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko				perror_msg_and_die("dup2");
494800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			close(fds[0]);
495800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
496800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
497800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
498800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	}
499800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
500800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	/* parent */
501800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	close(fds[0]);
502800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	swap_uid();
503800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	fp = fdopen(fds[1], "w");
504800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	if (!fp)
505800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		die_out_of_memory();
506800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko	return fp;
507800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko}
508800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko
5092e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkovoid
5102e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenkotprintf(const char *fmt, ...)
5112e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko{
5122e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_list args;
5132e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko
5142e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko	va_start(args, fmt);
5156764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	if (current_tcp) {
5166e4f3c1fa41851cb72230432db4be8e0c2993c7dDenys Vlasenko		int n = strace_vfprintf(current_tcp->outf, fmt, args);
5172e856a1c9215d292a7c41695928e8552788bc43cDenys Vlasenko		if (n < 0) {
5186764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			if (current_tcp->outf != stderr)
5199a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				perror_msg("%s", 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)
5369a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin			perror_msg("%s", 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)
734978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# undef PTRACE_DETACH
735978fbc901c4fe260caaa5881e54bd9cb54022101Denys 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. */
7539a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin			perror_msg("%s", "detach: ptrace(PTRACE_DETACH, ...)");
754800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
755800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		else if (my_tkill(tcp->pid, 0) < 0) {
756800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (errno != ESRCH)
7579a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				perror_msg("%s", "detach: checking sanity");
758800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		}
759800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko		else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
760800ec8ffde1296b3f2cfdd838fb08f2ff2bbe946Denys Vlasenko			if (errno != ESRCH)
7619a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin				perror_msg("%s", "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) {
7749a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin					perror_msg("%s", "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) {
7819a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin						perror_msg("%s", "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)
7889a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin							perror_msg("%s", "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) {
9379a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin					perror_msg("%s", "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) {
9589a71bcdab254e4cd93b8f1e93c659644eb70ea9bDmitry V. Levin			perror_msg("%s", "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
986f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko/* Stack-o-phobic exec helper, in the hope to work around
987f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko * NOMMU + "daemonized tracer" difficulty.
988f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko */
989f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkostruct exec_params {
990f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	int fd_to_close;
991f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	uid_t run_euid;
992f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	gid_t run_egid;
993f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	char **argv;
994f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	char *pathname;
995f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko};
996f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkostatic struct exec_params params_for_tracee;
997f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkostatic void __attribute__ ((noinline, noreturn))
998f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenkoexec_or_die(void)
999f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko{
1000f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	struct exec_params *params = &params_for_tracee;
1001f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
1002f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	if (params->fd_to_close >= 0)
1003f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		close(params->fd_to_close);
1004f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	if (!daemonized_tracer && !use_seize) {
1005f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
1006f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko			perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
1007f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		}
1008f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	}
1009f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
1010f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	if (username != NULL) {
1011f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		/*
1012f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * It is important to set groups before we
1013f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * lose privileges on setuid.
1014f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 */
1015f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		if (initgroups(username, run_gid) < 0) {
1016f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko			perror_msg_and_die("initgroups");
1017f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		}
1018f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		if (setregid(run_gid, params->run_egid) < 0) {
1019f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko			perror_msg_and_die("setregid");
1020f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		}
1021f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		if (setreuid(run_uid, params->run_euid) < 0) {
1022f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko			perror_msg_and_die("setreuid");
1023f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		}
1024f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	}
1025f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	else if (geteuid() != 0)
1026f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		if (setreuid(run_uid, run_uid) < 0) {
1027f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko			perror_msg_and_die("setreuid");
1028f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		}
1029f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
1030f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	if (!daemonized_tracer) {
1031f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		/*
1032f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * Induce a ptrace stop. Tracer (our parent)
1033f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * will resume us with PTRACE_SYSCALL and display
1034f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * the immediately following execve syscall.
1035f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * Can't do this on NOMMU systems, we are after
1036f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * vfork: parent is blocked, stopping would deadlock.
1037f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 */
1038f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		if (!NOMMU_SYSTEM)
1039f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko			kill(getpid(), SIGSTOP);
1040f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	} else {
1041f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		alarm(3);
1042f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		/* we depend on SIGCHLD set to SIG_DFL by init code */
1043f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		/* if it happens to be SIG_IGN'ed, wait won't block */
1044f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		wait(NULL);
1045f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		alarm(0);
1046f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	}
1047f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
1048f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	execv(params->pathname, params->argv);
1049f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	perror_msg_and_die("exec");
1050f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko}
1051f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
105202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
10531201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
105402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
105502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
105602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
105702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
1058f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	int pid;
105902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
106002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
106102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
106202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
106302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
106402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
1065cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
106602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
106702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
106802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
106902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
107002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
107102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
107202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
107302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
107402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
107502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
107602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
107702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
107802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
107930145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
108002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
108102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
108202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
10834f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			const char *colon = strchr(path, ':');
10844f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko			if (colon) {
10854f3df078b26899afe0f25d8651b06a5a5b5143e2Denys Vlasenko				n = colon - path;
108602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
108702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
108802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
108902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
109002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
109102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
109202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
109302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
109402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
109502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
109602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
109702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
109802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
109902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
110002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
110102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
110202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
110302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
110402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
110502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
110602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
110702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
110802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
110902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
111002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
111102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
111202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
111302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
1114cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
111502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
1116f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
1117f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	params_for_tracee.fd_to_close = (shared_log != stderr) ? fileno(shared_log) : -1;
1118f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	params_for_tracee.run_euid = (statbuf.st_mode & S_ISUID) ? statbuf.st_uid : run_uid;
1119f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	params_for_tracee.run_egid = (statbuf.st_mode & S_ISGID) ? statbuf.st_gid : run_gid;
1120f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	params_for_tracee.argv = argv;
1121f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	/*
1122f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 * On NOMMU, can be safely freed only after execve in tracee.
1123f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 * It's hard to know when that happens, so we just leak it.
1124f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 */
112505f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko	params_for_tracee.pathname = NOMMU_SYSTEM ? strdup(pathname) : pathname;
1126f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko
1127a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
1128ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
1129cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
1130ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
1131f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	if ((pid != 0 && daemonized_tracer)
1132f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 || (pid == 0 && !daemonized_tracer)
1133ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
1134f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		/* We are to become the tracee. Two cases:
1135f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * -D: we are parent
1136f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * not -D: we are child
1137f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 */
1138f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		exec_or_die();
113902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
1140ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
11412e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
114275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
11432e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
114431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!use_seize) {
114531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* child did PTRACE_TRACEME, nothing to do in parent */
114631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		} else {
11475c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko			if (!NOMMU_SYSTEM) {
114831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* Wait until child stopped itself */
114931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				int status;
115031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				while (waitpid(pid, &status, WSTOPPED) < 0) {
115131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (errno == EINTR)
115231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko						continue;
115331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("waitpid");
115431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
115531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
115675fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko					kill_save_errno(pid, SIGKILL);
115731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("Unexpected wait status %x", status);
115831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
115905f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko				skip_startup_execve = 1;
116031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
11615c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko			/* Else: NOMMU case, we have no way to sync.
116231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * Just attach to it as soon as possible.
116331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * This means that we may miss a few first syscalls...
116431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
116531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
116631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace_attach_or_seize(pid)) {
116775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko				kill_save_errno(pid, SIGKILL);
116831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				perror_msg_and_die("Can't attach to %d", pid);
116931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
11705c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko			if (!NOMMU_SYSTEM)
117131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGCONT);
117231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
11732e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
11745c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko		if (!NOMMU_SYSTEM)
117575fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
1176f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
117775fe85c2ee83a31afe0c8f1468da28deb1c2bc28Denys Vlasenko			tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
11783db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		newoutf(tcp);
11792e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
11802e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
118105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		/* With -D, we are *child* here, IOW: different pid. Fetch it: */
11822e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
11832e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
11842e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
1185f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		alloctcb(pid);
1186f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko		/* attaching will be done later, by startup_attach */
11873db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		/* note: we don't do newoutf(tcp) here either! */
118805f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		skip_startup_execve = 1;
11895c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko
1190f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		/* NOMMU BUG! -D mode is active, we (child) return,
1191f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * and we will scribble over parent's stack!
1192f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * When parent later unpauses, it segfaults.
1193f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 *
1194f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * We work around it
1195f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * (1) by declaring exec_or_die() NORETURN,
1196f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * hopefully compiler will just jump to it
1197f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * instead of call (won't push anything to stack),
1198f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * (2) by trying very hard in exec_or_die()
1199f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * to not use any stack,
1200f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * (3) having a really big (MAXPATHLEN) stack object
1201f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * in this function, which creates a "buffer" between
1202f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * child's and parent's stack pointers.
1203f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * This may save us if (1) and (2) failed
1204f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * and compiler decided to use stack in exec_or_die() anyway
1205f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 * (happens on i386 because of stack parameter passing).
120605f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		 *
120705f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		 * A cleaner solution is to use makecontext + setcontext
120805f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		 * to create a genuine separate stack and execute on it.
1209f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko		 */
1210ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
121102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
121202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1213b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
1214b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
1215b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
1216b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
1217b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
12188d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenkostatic int
12193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
1220b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
12212fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
12222fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
12232fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
12242fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
1225b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
122605f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko	/* Need fork for test. NOMMU has no forks */
122705f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko	if (NOMMU_SYSTEM)
122805f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		goto worked; /* be bold, and pretend that test succeeded */
122905f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko
12305d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
12315d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
123204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
12335d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
123404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
123531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
123604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
123704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
12384c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko		kill_save_errno(pid, SIGSTOP);
123904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
124004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
124104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
1242b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
1243b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
1244b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
1245b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
1246b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
124704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
1248b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
124904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
1250b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
1251b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
12524c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			if (errno == ECHILD)
1253b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
125404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
125504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
125604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
125704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
125804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
125904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
126004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
126104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
126204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
126304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
126404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
126504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
126604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
126704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
126804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
126904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
127004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
127104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
127204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
127304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
127404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
127504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
12764c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko			kill_save_errno(pid, SIGKILL);
127704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
127804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
1279b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
1280b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
12812fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
128204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
128304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
128404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
128504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
128604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
128704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
1288b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
128904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
129004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
129104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
129204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
129304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
129404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
129504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
129604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
129704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
12982fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
129904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
130004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
130104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
1302b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
130304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
130404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
130504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
130604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
130704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
1308b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
1309b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
131004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
131105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko worked:
1312f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1313a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
131404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
131504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
13168d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko		return 0;
131704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
131804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
131904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
13208d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	return 1;
1321b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
13223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
13243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
13253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
13263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
13273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
13283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
13293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
13303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
13313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
13323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
13333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
13343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
13353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
13363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
13378d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenkostatic int
13383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
13393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
134004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
134104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
13423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
13433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
13443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
134505f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko	/* Need fork for test. NOMMU has no forks */
13465c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko	if (NOMMU_SYSTEM)
134705f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko		goto worked; /* be bold, and pretend that test succeeded */
13487ff5ed932568a8049c3ca134da374f64c3e255ceMike Frysinger
13493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
13503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
135175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
13523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
13543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
13553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
135675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
135704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
135804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
13593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
13603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
13613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
13623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
13643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
13653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
13663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
13673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
13683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
13693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
13703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
137104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
137204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
137304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
137475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
137575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
137675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
137775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
137804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
137904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
138004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
138104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
138204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
138304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
13843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
13863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
138704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
138804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
13893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
13903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
13913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
13923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
13933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
13943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
13953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
13963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
139704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
139804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
139904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
14003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
14013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
14023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
14033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
14043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
140504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
140675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
14073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
14083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
14093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
14103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
141105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko worked:
141275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
1413f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
1414a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
1415f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1416f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
14178d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko		return 0;
14183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
14193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
142004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
142104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
14228d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	return 1;
14233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
142431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
14255c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE
142631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void
142731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void)
142831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
142931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int pid;
143031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
143105f325199a6cf36c92560d5a08b56652502705c2Denys Vlasenko	/* Need fork for test. NOMMU has no forks */
14325c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko	if (NOMMU_SYSTEM) {
14335c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
14345c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko		return;
14355c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko	}
14365c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko
143731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	pid = fork();
143831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid < 0)
143931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		perror_msg_and_die("fork");
144031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
144131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid == 0) {
144231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		pause();
144331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		_exit(0);
144431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
144531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
144631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	/* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap.  After
144731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * attaching tracee continues to run unless a trap condition occurs.
144831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * PTRACE_SEIZE doesn't affect signal or group stop state.
144931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 */
145026bc0606d96d05d30ba263939a0451889340a64cDenys Vlasenko	if (ptrace(PTRACE_SEIZE, pid, 0, 0) == 0) {
145131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
1452a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko	} else if (debug_flag) {
145331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
145431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
145531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
145631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	kill(pid, SIGKILL);
145731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
145831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	while (1) {
145931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int status, tracee_pid;
146031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
146131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		errno = 0;
146231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tracee_pid = waitpid(pid, &status, 0);
146331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (tracee_pid <= 0) {
146431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (errno == EINTR)
146531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
146631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d",
146731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					 __func__, tracee_pid);
146831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
146931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (WIFSIGNALED(status)) {
147031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			return;
147131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
147231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		error_msg_and_die("%s: unexpected wait status %x",
147331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				__func__, status);
147431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
147531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
1476978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#else /* !USE_SEIZE */
1477978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko# define test_ptrace_seize() ((void)0)
1478978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#endif
147931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
14806e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenkostatic unsigned
1481f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void)
1482f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{
14836e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	unsigned rel;
14846e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	const char *p;
1485f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	struct utsname u;
1486f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (uname(&u) < 0)
1487f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		perror_msg_and_die("uname");
14886e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	/* u.release has this form: "3.2.9[-some-garbage]" */
14896e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	rel = 0;
14906e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	p = u.release;
14916e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	for (;;) {
14926e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (!(*p >= '0' && *p <= '9'))
14936e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
14946e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		/* Note: this open-codes KERNEL_VERSION(): */
14956e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		rel = (rel << 8) | atoi(p);
14966e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (rel >= KERNEL_VERSION(1,0,0))
14976e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			break;
14986e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		while (*p >= '0' && *p <= '9')
14996e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			p++;
15000dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin		if (*p != '.') {
15010dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin			if (rel >= KERNEL_VERSION(0,1,0)) {
15020dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin				/* "X.Y-something" means "X.Y.0" */
15030dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin				rel <<= 8;
15040dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin				break;
15050dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin			}
15066e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko			error_msg_and_die("Bad OS release string: '%s'", u.release);
15070dbc80de895c25769791b7726022a274695eec31Dmitry V. Levin		}
15086e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		p++;
15096e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	}
15106e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	return rel;
1511f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko}
1512f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1513ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko/*
1514ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Initialization part of main() was eating much stack (~0.5k),
1515ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * which was unused after init.
1516ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * We can reuse it if we move init code into a separate function.
1517ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko *
1518ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * Don't want main() to inline us and defeat the reason
1519ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko * we have a separate function.
1520ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko */
1521ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkostatic void __attribute__ ((noinline))
1522ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoinit(int argc, char *argv[])
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
1525ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin	int c, i;
152606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
153008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
1531a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	/* Make sure SIGCHLD has the default action so that waitpid
1532a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   definitely works without losing track of children.  The user
1533a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   should not have given us a bogus state to inherit, but he might
1534a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   have.  Arguably we should detect SIG_IGN here and pass it on
1535a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	   to children, but probably noone really needs that.  */
1536a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko	signal(SIGCHLD, SIG_DFL);
1537a509054aeee00a89a2250919f74bd849c67ded61Denys Vlasenko
153875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
153975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
15406e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko	os_release = get_os_release();
1541f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1542ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
1543ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
15444f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
15451d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
15461d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
15474f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
15481d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
15491d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
15504f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
15514f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
1552ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
15536764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko	shared_log = stderr;
1554138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
1555138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
155974ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko#if DEFAULT_QUAL_FLAGS != (QUAL_TRACE | QUAL_ABBREV | QUAL_VERBOSE)
156074ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko# error Bug in DEFAULT_QUAL_FLAGS
156174ec14f968a418691b851cbbfeb0269174c64b08Denys Vlasenko#endif
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
156461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		"+bcCdfFhiqrtTvVxyz"
1565ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1566b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
156861e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		case 'b':
156961e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			detach_on_execve = 1;
157061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			break;
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1572e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1573c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive");
1574e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1575e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1576e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1577e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1578e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1579c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive");
1580e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1581e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
1584a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			debug_flag = 1;
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1586ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1587ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1588ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
158941c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
159006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
159106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
1599a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			iflag = 1;
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
1602a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			qflag = 1;
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
1605a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			rflag = 1;
1606a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			/* fall through to tflag++ */
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
1611a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			Tflag = 1;
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
16168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
16178a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
16188a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
16239c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
162617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
162717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
162817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
1630ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			acolumn = string_to_uint(optarg);
1631102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1632ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
1641ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			i = string_to_uint(optarg);
1642ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			if (i < 0)
1643ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
1644ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			set_overhead(i);
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1647e8172b79e3dd35a136f4dc4d4de9df5bb4565c01Denys Vlasenko			process_opt_p_list(optarg);
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
16498a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
16508a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
16518a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1652cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
16538a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
16548a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
1656ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			i = string_to_uint(optarg);
1657ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			if (i < 0)
1658ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
1659ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			max_strlen = i;
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1667de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
16681d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
16691d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1670de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
1671b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		case 'I':
1672ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			opt_intr = string_to_uint(optarg);
1673ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin			if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS)
1674ccee169ab6aa4ae7515198dadcef5dd2286ede4bDmitry V. Levin				error_opt_arg(c, optarg);
1675b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			break;
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1681837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1682837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1684102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1685102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
16861d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1687102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1688102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1689102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1690837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1691fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (!argv[0] == !nprocs)
1692ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1693ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1694fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 && daemonized_tracer) {
1695c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive");
1696d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1697d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
169806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
169906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
170006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
17013db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko	if (followfork >= 2 && cflag) {
1702c5ccfa450b9818ef9eab94f9d15189e50a796937Denys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive");
1703cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1704cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1710cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17125d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
17135d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1714cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17248d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	/*
17258d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	 * On any reasonably recent Linux kernel (circa about 2.5.46)
17268d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	 * need_fork_exec_workarounds should stay 0 after these tests:
17278d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	 */
17288d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	/*need_fork_exec_workarounds = 0; - already is */
172904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
17308d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko		need_fork_exec_workarounds = test_ptrace_setoptions_followfork();
17318d4ca0c8cd81329ad730ab52b1e0653c1bbea803Denys Vlasenko	need_fork_exec_workarounds |= test_ptrace_setoptions_for_all();
173231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	test_ptrace_seize();
17338044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
173637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
173737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
173837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
173937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
174037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
174137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
17423db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko			if (followfork >= 2)
17437dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
17446764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			shared_log = strace_popen(outfname + 1);
174554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
17463db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		else if (followfork < 2)
17476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			shared_log = strace_fopen(outfname);
1748328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko	} else {
1749328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko		/* -ff without -o FILE is the same as single -f */
17503db3b26101443dccbea959ba0abcbffb240d04e8Denys Vlasenko		if (followfork >= 2)
1751328bf250bde8167cec6f2f5bf35463fb4ffb6f9fDenys Vlasenko			followfork = 1;
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1754cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1755a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1756a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1757a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
17586764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		setvbuf(shared_log, buf, _IOLBF, BUFSIZ);
1759cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1760837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
1761b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (!opt_intr)
1762b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = INTR_NEVER;
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1764369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1765b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (!opt_intr)
1766b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		opt_intr = INTR_WHILE_WAIT;
1767b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
1768b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	/* argv[0]	-pPID	-oFILE	Default interactive setting
1769b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	0	INTR_WHILE_WAIT
1770b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	0	INTR_WHILE_WAIT
1771b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	1	INTR_NEVER
1772b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	1	INTR_WHILE_WAIT
177354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
177454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
17755c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko	sigemptyset(&empty_set);
17765c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko	sigemptyset(&blocked_set);
17775c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko
1778f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	/* startup_child() must be called before the signal handlers get
1779f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 * installed below as they are inherited into the spawned process.
1780f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 * Also we do not need to be protected by them as during interruption
1781f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 * in the startup_child() mode we kill the spawned process anyway.
1782f909c8d0d759d0511ad2c741854602b0494e0390Denys Vlasenko	 */
178361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	if (argv[0]) {
1784837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
178561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko	}
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
1790b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1791b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1792b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (opt_intr != INTR_ANYWHERE) {
1793b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_BLOCK_TSTP_TOO)
1794b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1795b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/*
1796b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1797b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * fatal signals are blocked while syscall stop is processed,
1798b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * and acted on in between, when waiting for new syscall stops.
1799b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In non-interactive mode, signals are ignored.
1800b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 */
1801b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_WHILE_WAIT) {
1802b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGHUP);
1803b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGINT);
1804b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGQUIT);
1805b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGPIPE);
1806b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGTERM);
1807b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_handler = interrupt;
1808b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		}
1809b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/* SIG_IGN, or set handler for these */
1810b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGHUP, &sa, NULL);
1811b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGINT, &sa, NULL);
1812b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGQUIT, &sa, NULL);
1813b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGPIPE, &sa, NULL);
1814b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGTERM, &sa, NULL);
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1816fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	if (nprocs != 0 || daemonized_tracer)
181702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
181802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
1819fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	/* Do we want pids printed in our -o OUTFILE?
1820fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -ff: no (every pid has its own file); or
1821fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -f: yes (there can be more pids in the future); or
1822fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 * -p PID1,PID2: yes (there are already more than one pid)
1823fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	 */
1824fd883380671693a4616881a9103491f9e67fc8aeDenys Vlasenko	print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1827eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
182854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
183154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
183254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
183354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1835ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
183654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
183754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18451201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
18493521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	int fatal_sig;
18503521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko
18513521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	/* 'interrupted' is a volatile object, fetch it only once */
18523521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	fatal_sig = interrupted;
18533521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	if (!fatal_sig)
18543521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko		fatal_sig = SIGTERM;
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1856ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1857ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
1860a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag)
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
18637de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		if (tcp->flags & TCB_STRACE_CHILD) {
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
1865a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko			kill(tcp->pid, fatal_sig);
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
18677de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		detach(tcp);
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
18706764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		call_summary(shared_log);
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18741201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
1876a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko	interrupted = sig;
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18801201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
188326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
1884978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#ifdef __WALL
1885eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
1886978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#endif
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1888eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
1889f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int pid;
1890f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int wait_errno;
1891f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int status, sig;
189231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int stopped;
1893f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		struct tcb *tcp;
1894f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		unsigned event;
1895f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1896222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
1897eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
1898eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1899eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
1900978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#ifdef __WALL
190126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
19025bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
19032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
19042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
190526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
19062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
19075bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
19082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
190926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
191026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
1911cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
19122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
19132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
1914978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#else
191526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
1916978fbc901c4fe260caaa5881e54bd9cb54022101Denys Vlasenko#endif /* __WALL */
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
1918eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
1919eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
1922eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
1923eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1925eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
1932eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
1933eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
1934eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
19354c65c44478f1591d96cda425d78451334fe1d401Denys Vlasenko				perror_msg("wait");
1936eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
193910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
194010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
19417dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
194210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
194310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
1944f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1945f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		event = ((unsigned)status >> 16);
1946a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko		if (debug_flag) {
19471d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
194867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			char evbuf[sizeof(",PTRACE_EVENT_?? (%u)") + sizeof(int)*3 /*paranoia:*/ + 16];
19491d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
19501d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
19511d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
19521d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
19531d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
19541d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
19551d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
19561d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
19571d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
19581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
19591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
19601d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
19611d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
19621d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
19635bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
19641d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
19651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
19665bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
196767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			evbuf[0] = '\0';
196867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			if (event != 0) {
196967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				static const char *const event_names[] = {
197067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
197167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
197267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
197367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
197467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
197567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
197667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				};
197767559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				const char *e;
197867559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				if (event < ARRAY_SIZE(event_names))
197967559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = event_names[event];
198067559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				else {
198167559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					sprintf(buf, "?? (%u)", event);
198267559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko					e = buf;
198367559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				}
198467559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko				sprintf(evbuf, ",PTRACE_EVENT_%s", e);
198567559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			}
198667559ad260fd31c823615f650f5e131818acf20fDenys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s%s\n", status, pid, buf, evbuf);
19871d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1989f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Look up 'pid' in our table. */
19905d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
1991f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
19928511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko		if (!tcp) {
19938511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (followfork) {
19948511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tcp = alloctcb(pid);
19958511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
19968511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				newoutf(tcp);
19978511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				if (!qflag)
19988511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
19998511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko						pid);
20008511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			} else {
20018511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				/* This can happen if a clone call used
20028511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				   CLONE_PTRACE itself.  */
20038511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				if (WIFSTOPPED(status))
20048511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko					ptrace(PTRACE_CONT, pid, (char *) 0, 0);
20058511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
20068511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			}
20078511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko		}
20088511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko
2009ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko		clear_regs();
2010ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko		if (WIFSTOPPED(status))
2011ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko			get_regs(pid);
2012ce7d953ebecc10f71e191b6d18cfeb2399429d5fDenys Vlasenko
2013f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Under Linux, execve changes pid to thread leader's pid,
2014f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and we see this changed pid on EVENT_EXEC and later,
2015f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * execve sysexit. Leader "disappears" without exit
2016f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * notification. Let user know that, drop leader's tcb,
2017f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and fix up pid in execve thread's tcb.
2018f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * Effectively, execve thread's tcb replaces leader's tcb.
2019f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
2020f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2021f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * on exit syscall) in multithreaded programs exactly
2022f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * in order to handle this case.
2023f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
2024f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2025f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * On 2.6 and earlier, it can return garbage.
2026f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 */
20276e0bfd11ac1aa36713d9a65542ae86dd607ae374Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
20286764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			FILE *fp;
20298511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			struct tcb *execve_thread;
2030f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			long old_pid = 0;
20318511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko
20328511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) < 0)
20338511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				goto dont_switch_tcbs;
20348511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (old_pid <= 0 || old_pid == pid)
20358511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				goto dont_switch_tcbs;
20368511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			execve_thread = pid2tcb(old_pid);
20378511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* It should be !NULL, but I feel paranoid */
20388511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (!execve_thread)
20398511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				goto dont_switch_tcbs;
20408511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko
20418511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (execve_thread->curcol != 0) {
20428511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				/*
20438511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				 * One case we are here is -ff:
20448511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				 * try "strace -oLOG -ff test/threaded_execve"
20458511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				 */
20468511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				fprintf(execve_thread->outf, " <pid changed to %d ...>\n", pid);
20476764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko				/*execve_thread->curcol = 0; - no need, see code below */
20488511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			}
20498511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* Swap output FILEs (needed for -ff) */
20506764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			fp = execve_thread->outf;
20516764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			execve_thread->outf = tcp->outf;
20526764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			tcp->outf = fp;
20538511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* And their column positions */
20546764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			execve_thread->curcol = tcp->curcol;
20556764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko			tcp->curcol = 0;
20568511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* Drop leader, but close execve'd thread outfile (if -ff) */
20578511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			droptcb(tcp);
20588511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			/* Switch to the thread, reusing leader's outfile and pid */
20598511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			tcp = execve_thread;
20608511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			tcp->pid = pid;
20618511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko			if (cflag != CFLAG_ONLY_STATS) {
20628511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				printleader(tcp);
20638511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
20648511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				line_ended();
20658511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko				tcp->flags |= TCB_REPRINT;
2066f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			}
2067f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		}
20688511f2a1f02a31f66eab86bf95dee1636fb39076Denys Vlasenko dont_switch_tcbs:
2069f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
207061e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && detach_on_execve) {
207161e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			if (!skip_startup_execve)
207261e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko				detach(tcp);
207361e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			/* This was initial execve for "strace PROG". Skip. */
207461e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko			skip_startup_execve = 0;
207561e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko		}
207661e7aad9fa1a6a5bd5a586e6276767caf12b53f2Denys Vlasenko
20777de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko		/* Set current output file */
20786764f8f2f0b71ecc069d607eb8525735d1684a59Denys Vlasenko		current_tcp = tcp;
20797de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko
208013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2084eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2086a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2087a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2088e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2089a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko			 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)
2090a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko			) {
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
209213d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
2093000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s %s+++\n",
20942efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
209513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
209613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
2097000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s +++\n",
209813d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
20992efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
21007de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2106a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
2108b5e0908a173cc8005ed73fa5c0eab59d03baa7f3Denys Vlasenko			if (cflag != CFLAG_ONLY_STATS) {
210919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
2110000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
21117de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
211219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2122f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
2123f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
2124a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2125f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
212702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
212902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
21302ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
21326cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
21336cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
2140a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko				if (debug_flag)
214144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
214244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
214344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
214444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
214544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
21463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
21473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
21483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2149f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2150f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
215131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		sig = WSTOPSIG(status);
215231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
2153f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event != 0) {
215431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Ptrace event */
21555c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE
215626bc0606d96d05d30ba263939a0451889340a64cDenys Vlasenko			if (event == PTRACE_EVENT_STOP) {
21576703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				/*
21586703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop or group-stop.
21596703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
21606703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 */
216131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (sig == SIGSTOP
216231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTSTP
216331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTIN
216431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTOU
216531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				) {
216631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					stopped = 1;
216731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					goto show_stopsig;
216831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
216931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
217031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
2171f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2172f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2173f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2174f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2175f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2176f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2177f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2178f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2179f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2180f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2181a50d2a87a1a8df4471bbd93f2ce9ef0541b1124bDenys Vlasenko			if (debug_flag)
2182f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2183f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
21846cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21876cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
218831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			siginfo_t si;
218931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
219031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Nonzero (true) if tracee is stopped by signal
219131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * (as opposed to "tracee received signal").
2192a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8aDenys Vlasenko			 * TODO: shouldn't we check for errno == EINVAL too?
2193a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8aDenys Vlasenko			 * We can get ESRCH instead, you know...
219431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
219531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
21965c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE
219731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig:
21986703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif
2199e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2200a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko			 && (qual_flags[sig] & QUAL_SIGNAL)
2201a9fe13c9437707fa132fde4e51a20d88381e7430Denys Vlasenko			) {
2202c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
22036b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
22046b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
22057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2206932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2207932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
22087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
22096b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
22107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
22116b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
22122ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
22136b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
22142ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
22152ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
22167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
221831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!stopped) {
22192c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf("--- %s ", signame(sig));
22206b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
22212c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf(PC_FORMAT_STR " ---\n"
22226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
22236b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
22242c4fb905fef268a7e359ce3acaec4ee7ef087996Denys Vlasenko					tprintf("--- stopped by %s" PC_FORMAT_STR " ---\n",
22256cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
22266b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
22277de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko				line_ended();
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
222931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
223031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!stopped)
223131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* It's signal-delivery-stop. Inject the signal */
223231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				goto restart_tracee;
223331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
223431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* It's group-stop */
22355c9d8f4fc5318fc740ec2a16bac5b8a29e7eb52dDenys Vlasenko#if USE_SEIZE
223631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (use_seize) {
223731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/*
223831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This ends ptrace-stop, but does *not* end group-stop.
223931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This makes stopping signals work properly on straced process
224031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * (that is, process really stops. It used to continue to run).
224131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 */
224231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
224331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cleanup();
224431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					return -1;
224531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
224631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
224731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
224831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* We don't have PTRACE_LISTEN support... */
224931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
22506cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22522ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
22532ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
225402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
225502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
22562ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
22572ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
22582ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
22592ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
22602ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2261235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko		if (trace_syscall(tcp) < 0) {
2262235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko			/* ptrace() failed in trace_syscall().
2263eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2264235067525cc064a9a466c245fa8a6265ae136306Denys Vlasenko			 * Observed case: exit_group() or SIGKILL terminating
2265f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
22667de265d88a78a27d58c2c728424e5bb8379ef351Denys Vlasenko			 * We assume that ptrace error was caused by process death.
2267f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * We used to detach(tcp) here, but since we no longer
2268f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * implement "detach before death" policy/hack,
2269f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * we can let this process to report its death to us
2270f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 * normally, via WIFEXITED or WIFSIGNALED wait status.
2271f20250266eb5988805b03b1cc0fa74cdb6398742Denys Vlasenko			 */
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22746cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
22756cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
22766cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
22776cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
2284ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2285ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkoint
2286ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenkomain(int argc, char *argv[])
2287ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko{
2288ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	init(argc, argv);
2289ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2290ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	/* Run main tracing loop */
2291ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (trace() < 0)
2292ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		return 1;
2293ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2294ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	cleanup();
2295ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	fflush(NULL);
2296cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin	if (shared_log != stderr)
2297cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin		fclose(shared_log);
2298cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin	if (popen_pid) {
2299cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin		while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
2300cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin			;
2301cf53436f737c0273028503186fc0f837c7191085Dmitry V. Levin	}
2302ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	if (exit_code > 0xff) {
2303ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Avoid potential core file clobbering.  */
2304ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		struct rlimit rlim = {0, 0};
2305ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		setrlimit(RLIMIT_CORE, &rlim);
2306ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2307ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Child was killed by a signal, mimic that.  */
2308ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code &= 0xff;
2309ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		signal(exit_code, SIG_DFL);
2310ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		raise(exit_code);
2311ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		/* Paranoia - what if this signal is not fatal?
2312ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		   Exit with 128 + signo then.  */
2313ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko		exit_code += 128;
2314ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	}
2315ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko
2316ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko	return exit_code;
2317ecc8b97c9bd36ad25c550ec412f43f44b59e2ebdDenys Vlasenko}
2318