strace.c revision b87d30c785679b37a2ec7242881f0d0b819c738d
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* 276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved. 776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without 976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions 1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met: 1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright 1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer. 1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright 1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer in the 1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * documentation and/or other materials provided with the distribution. 1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products 1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * derived from this software without specific prior written permission. 1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * $Id$ 3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h" 3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h> 3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h> 3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h> 3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h> 3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h> 4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h> 4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h> 4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h> 4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h> 4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h> 4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h> 4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h> 4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h> 4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 49134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX 50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h> 51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill 52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig)) 53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill 54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig)) 55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else 56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath /* kill() may choose arbitrarily the target task of the process group 57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath while we later wait on a that specific TID. PID process waits become 58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath TID task specific waits for a process under ptrace(2). */ 59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!" 60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) kill ((tid), (sig)) 61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif 62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif 63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath 647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX) 657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h> 70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 74ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H 769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif 8096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ; 81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind; 82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg; 8396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko 8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8541c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0; 86e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0; 87e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE; 88b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0; 89ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/* 90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option. 91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice. 92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's, 93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process 94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild 95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID. 96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases 97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals, 98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between, 99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link. 100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0; 10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0; 10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 106a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0; 107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0; 108eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 109b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL; 11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 115b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL; 11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 117ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol; 118ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab; 119ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize; 12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname; 121eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ; 12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 123e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig); 124e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void); 125e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void); 126e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig); 12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 135bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 137e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd); 138e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig); 139e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void); 140ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv; 14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void); 145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd); 14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 158ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 171b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwabusage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 172de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 173de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 174b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 175de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 177b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\ 17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 192ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\ 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 196de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 197de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it 19917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 200de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath */ 201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 214c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */ 215c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK 216c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0 217c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else 218c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1 219c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork() vfork() 220c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif 221c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger 22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd) 22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int flags, newflags; 22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((flags = fcntl(fd, F_GETFD, 0)) < 0) 22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_GETFD: %s\n", 23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newflags = flags | FD_CLOEXEC; 23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (flags == newflags) 23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fcntl(fd, F_SETFD, newflags) < 0) 23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_SETFD: %s\n", 24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids 25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations. 25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void 25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void) 25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4 25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int euid = geteuid(), uid = getuid(); 25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (euid != uid && setreuid(euid, uid) < 0) 25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: setreuid: %s\n", 26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin exit(1); 26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 26410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 2674bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE 2684bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64 2694bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else 2704bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen 2714bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif 2724bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath 27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode) 27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 2794bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath if ((fp = fopen_for_output(path, mode)) == NULL) 28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: can't fopen '%s': %s\n", 28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, path, strerror(errno)); 28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fp && set_cloexec_flag(fileno(fp)) < 0) 28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fclose(fp); 28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fp = NULL; 28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fp; 28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1; 29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL 29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh" 29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish 29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3) 30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid. 30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command) 30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int fds[2]; 30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pipe(fds) < 0) 30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: pipe: %s\n", 31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(fds[1]) < 0) 31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((popen_pid = fork()) == -1) 32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fork: %s\n", 32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (popen_pid) 33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* parent */ 33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fdopen(fds[1], "w"); 34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } else 34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* child */ 34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fds[0] && (dup2(fds[0], 0) || close(fds[0]))) 34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: dup2: %s\n", 34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin execl(_PATH_BSHELL, "sh", "-c", command, NULL); 35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: execl: %s: %s\n", 35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, _PATH_BSHELL, strerror(errno)); 35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp) 35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (outfname && followfork > 1) { 3617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char name[520 + sizeof(int) * 3]; 36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3647a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko sprintf(name, "%.512s.%u", outfname, tcp->pid); 36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((fp = strace_fopen(name, "w")) == NULL) 36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin tcp->outf = fp; 36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void) 37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tcbi; 37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Block user interruptions as we would leave the traced 38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * process stopped (process state T) if we would terminate in 38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * between PTRACE_ATTACH and wait4 () on SIGSTOP. 38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * We rely on cleanup () from this point on. 38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 38402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 38502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 38602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid_t pid = fork(); 389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(1); 391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid) { /* parent */ 393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Wait for child to attach to straced process 395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * (our parent). Child SIGKILLs us after it attached. 396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Parent's wait() is unblocked by our death, 397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * it proceeds to exec the straced program. 398ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 399ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pause(); 400ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(0); /* paranoia */ 401ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 402ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 403ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = tcbtab[tcbi]; 40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX 40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif 41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Reinitialize the output since it may have changed. */ 41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->outf = outf; 41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (newoutf(tcp) < 0) 41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (proc_open(tcp, 1) < 0) { 41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "trouble opening proc file\n"); 42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX 425ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (followfork && !daemonized_tracer) { 4267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; 42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath DIR *dir; 42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath dir = opendir(procdir); 43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (dir != NULL) { 43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath unsigned int ntid = 0, nerr = 0; 43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct dirent *de; 43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tid; 43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath while ((de = readdir(dir)) != NULL) { 4367a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (de->d_fileno == 0) 43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tid = atoi(de->d_name); 43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tid <= 0) 44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++ntid; 442aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) 44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++nerr; 444aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko else if (tid != tcbtab[tcbi]->pid) { 445418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(tid); 446eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK; 44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nchildren++; 44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_threads++; 44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_detached++; 45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->parent = tcbtab[tcbi]; 45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 452aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (interactive) { 453aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko sigprocmask(SIG_SETMASK, &empty_set, NULL); 454aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (interrupted) 455aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko return; 456aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko sigprocmask(SIG_BLOCK, &blocked_set, NULL); 457aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko } 45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath closedir(dir); 4607a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ntid -= nerr; 4617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (ntid == 0) { 46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) { 4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko fprintf(stderr, ntid > 1 4687a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n" 4697a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n", 4707a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko tcbtab[tcbi]->pid, ntid); 47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 4737a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (opendir worked) */ 4747a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (-f) */ 47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif 47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* INTERRUPTED is going to be checked at the top of TRACE. */ 482ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 484ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It is our grandparent we trace, not a -p PID. 486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Don't want to just detach on exit, so... 487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags &= ~TCB_ATTACHED; 489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make parent go away. 491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Also makes grandparent's wait() unblock. 492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(getppid(), SIGKILL); 494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 495ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) 49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, 49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath "Process %u attached - interrupt to quit\n", 50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv) 50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct stat statbuf; 51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath const char *filename; 51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char pathname[MAXPATHLEN]; 51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int pid = 0; 51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath filename = argv[0]; 51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(filename, '/')) { 51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath errno = ENAMETOOLONG; 52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC 52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Debuggers customarily check the current directory 52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * first regardless of the path but doing that gives 52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * security geeks a panic attack. 53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (stat(filename, &statbuf) == 0) 53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */ 53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char *path; 53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int m, n, len; 53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (path = getenv("PATH"); path && *path; path += m) { 53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(path, ':')) { 54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath n = strchr(path, ':') - path; 54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n + 1; 54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n = strlen(path); 54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (n == 0) { 54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!getcwd(pathname, MAXPATHLEN)) 54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = strlen(pathname); 54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (n > sizeof pathname - 1) 55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strncpy(pathname, path, n); 55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = n; 55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (len && pathname[len - 1] != '/') 55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pathname[len++] = '/'; 55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname + len, filename); 55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) == 0 && 56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Accept only regular files 56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath with some execute bits set. 56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath XXX not perfect, might still fail */ 56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath S_ISREG(statbuf.st_mode) && 56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (statbuf.st_mode & 0111)) 56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) < 0) { 56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "%s: %s: command not found\n", 57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath progname, filename); 57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 573a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin strace_child = pid = fork(); 574ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: fork"); 57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath cleanup(); 57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 578ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 579ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */ 580ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */ 581ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko ) { 582ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid = getpid(); 58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf != stderr) close (fileno (outf)); 58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS 58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Kludge for SGI, see proc_open for details. */ 58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_handler = foobar; 58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_flags = 0; 58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigemptyset(&sa.sa_mask); 59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigaction(SIGINT, &sa, NULL); 59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */ 59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD 59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pause(); 59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */ 595ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); /* stop HERE */ 59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */ 59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf!=stderr) 59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath close(fileno (outf)); 60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 601ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 602ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko perror("strace: ptrace(PTRACE_TRACEME, ...)"); 604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko exit(1); 605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (debug) 607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); 60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL || geteuid() == 0) { 61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath uid_t run_euid = run_uid; 61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath gid_t run_egid = run_gid; 61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISUID) 61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_euid = statbuf.st_uid; 61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISGID) 61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_egid = statbuf.st_gid; 61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * It is important to set groups before we 62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * lose privileges on setuid. 62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL) { 62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (initgroups(username, run_gid) < 0) { 62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("initgroups"); 62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setregid(run_gid, run_egid) < 0) { 62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setregid"); 63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setreuid(run_uid, run_euid) < 0) { 63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setreuid"); 63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath setreuid(run_uid, run_uid); 64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Induce an immediate stop so that the parent 644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will resume us with PTRACE_SYSCALL and display 645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * this execve call normally. 646c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * Unless of course we're on a no-MMU system where 647c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * we vfork()-ed, so we cannot stop the child. 648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 649c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger if (!strace_vforked) 650c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger kill(getpid(), SIGSTOP); 651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } else { 652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko struct sigaction sv_sigchld; 653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko sigaction(SIGCHLD, NULL, &sv_sigchld); 654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make sure it is not SIG_IGN, otherwise wait 656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will not block. 657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko signal(SIGCHLD, SIG_DFL); 659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Wait for grandchild to attach to us. 661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It kills child after that, and wait() unblocks. 662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko alarm(3); 664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko wait(NULL); 665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko alarm(0); 666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko sigaction(SIGCHLD, &sv_sigchld, NULL); 667ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath execv(pathname, argv); 67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath _exit(1); 67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* We are the tracer. */ 676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp = alloctcb(daemonized_tracer ? getppid() : pid); 677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* We want subsequent startup_attach() to attach to it. */ 679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags |= TCB_ATTACHED; 680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (proc_open(tcp, 0) < 0) { 683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko fprintf(stderr, "trouble opening proc file\n"); 684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko cleanup(); 685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko exit(1); 68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */ 68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 69108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[]) 69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 69506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin int optF = 0; 69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[BUFSIZ]; 69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 70008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin progname = argv[0] ? argv[0] : "strace"; 70108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin 702ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 703ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 704418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) { 70508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 70608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 70708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 708418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) { 70908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 71008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 71108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 712ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp) 713ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]]; 714ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 717138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_sortby(DEFAULT_SORTBY); 718138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_personality(DEFAULT_PERSONALITY); 71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 724e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin "+cCdfFhiqrtTvVxz" 725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "D" 727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 728ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "a:e:o:O:p:s:S:u:E:")) != EOF) { 72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 731e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_BOTH) { 732e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin fprintf(stderr, "%s: -c and -C are mutually exclusive options\n", 733e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin progname); 734e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin exit(1); 735e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 736e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_ONLY_STATS; 737e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin break; 738e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin case 'C': 739e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_ONLY_STATS) { 740e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin fprintf(stderr, "%s: -c and -C are mutually exclusive options\n", 741e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin progname); 742e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin exit(1); 743e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 744e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_BOTH; 74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 750ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko case 'D': 751ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko daemonized_tracer = 1; 752ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko break; 753ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 75441c48227a86a176da333f713d5047240885f25ccRoland McGrath case 'F': 75506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin optF = 1; 75606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin break; 75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 7869c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 78917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 79017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 79117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 805de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if ((pid = atoi(optarg)) <= 0) { 80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 81154a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 814418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloc_tcb(pid, 0); 81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 820dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath if (max_strlen < 0) { 821dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath fprintf(stderr, 822dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath "%s: invalid -s argument: %s\n", 823dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath progname, optarg); 824dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath exit(1); 825dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath } 82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 833de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 834de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if (putenv(optarg) < 0) { 835de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 836de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath progname); 837de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath exit(1); 838de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath } 839de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 846d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath if ((optind == argc) == !pflag_seen) 847ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 848ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 84906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin if (!followfork) 85006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin followfork = optF; 85106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin 852cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath if (followfork > 1 && cflag) { 853cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath fprintf(stderr, 854e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin "%s: (-c or -C) and -ff are mutually exclusive options\n", 855cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath progname); 856cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath exit(1); 857cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath } 858cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath 85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 87109553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath progname, username); 87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 88437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 88537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 88637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 88737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 88837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 88937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 89037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (followfork > 1) { 89137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath fprintf(stderr, "\ 89237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n", 89337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath progname); 89437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 89537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 89637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath 89710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((outf = strace_popen(outfname + 1)) == NULL) 89837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 89954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 90010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin else if (followfork <= 1 && 90110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin (outf = strace_fopen(outfname, "w")) == NULL) 90254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 90537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (!outfname || outfname[0] == '|' || outfname[0] == '!') 90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 90737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname && optind < argc) { 90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 910369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 91154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* Valid states here: 91254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath optind < argc pflag_seen outfname interactive 91354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 0 1 91454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 0 1 91554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 1 0 91654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 1 1 91754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath */ 91854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 91954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* STARTUP_CHILD must be called before the signal handlers get 92054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath installed below as they are inherited into the spawned process. 92154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath Also we do not need to be protected by them as during interruption 92254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath in the STARTUP_CHILD mode we kill the spawned process anyway. */ 92354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath if (!pflag_seen) 92454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath startup_child(&argv[optind]); 92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 950bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 953553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 954553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath /* Make sure SIGCHLD has the default action so that waitpid 955553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath definitely works without losing track of children. The user 956553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath should not have given us a bogus state to inherit, but he might 957553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath have. Arguably we should detect SIG_IGN here and pass it on 958553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath to children, but probably noone really needs that. */ 959553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sa.sa_handler = SIG_DFL; 960553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sigaction(SIGCHLD, &sa, NULL); 961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 963ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pflag_seen || daemonized_tracer) 96402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_attach(); 96502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 969a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin fflush(NULL); 970a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (exit_code > 0xff) { 971a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Child was killed by a signal, mimic that. */ 972a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code &= 0xff; 973a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin signal(exit_code, SIG_DFL); 974a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin raise(exit_code); 975a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Paranoia - what if this signal is not fatal? 976a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin Exit with 128 + signo then. */ 977a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code += 128; 978a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin } 979a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit(exit_code); 98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 982418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid 983418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void) 9847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{ 9857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath /* Allocate some more TCBs and expand the table. 9867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath We don't want to relocate the TCBs because our 9877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath callers have pointers and it would be a pain. 9887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath So tcbtab is a table of pointers. Since we never 9897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free the TCBs, we allocate a single chunk of many. */ 9907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb **newtab = (struct tcb **) 9917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]); 9927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize, 9937b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath sizeof *newtcbs); 9947b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath int i; 9957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab == NULL || newtcbs == NULL) { 99676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin fprintf(stderr, "%s: expand_tcbtab: out of memory\n", 99776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin progname); 998418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko cleanup(); 999418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko exit(1); 10007b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath } 10017b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath for (i = tcbtabsize; i < 2 * tcbtabsize; ++i) 10027b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath newtab[i] = &newtcbs[i - tcbtabsize]; 10037b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtabsize *= 2; 10047b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtab = newtab; 10057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath} 10067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 100810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed) 100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1013418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if (nprocs == tcbtabsize) 1014418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko expand_tcbtab(); 1015418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko 1016ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1017ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 1020eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->parent = NULL; 1021eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nchildren = 0; 1022eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nzombies = 0; 1023eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD 1024eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nclone_threads = tcp->nclone_detached = 0; 1025eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nclone_waiting = 0; 1026eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif 102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 1029ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = 0; 1030eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->stime.tv_sec = 0; 1031eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->stime.tv_usec = 0; 103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 103410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (command_options_parsed) 103510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newoutf(tcp); 103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1039418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko fprintf(stderr, "%s: bug in alloc_tcb\n", progname); 1040418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko cleanup(); 1041418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko exit(1); 104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1044bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 1046418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching) 104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 1050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 105119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 105219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 1055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1060ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 10619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 10649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 10659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 106710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 10689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 10719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 10729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 10739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 107510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_stat) < 0) { 10769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 10799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 10809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 10819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 108310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_as) < 0) { 10849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 1088bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) { 1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 1093bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR)) < 0) { 1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 10999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 11019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 1102bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 1104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 1105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 1106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 1109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 1110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 1111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 1112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 11249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 11289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 1129bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman break; 113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1132bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 113416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1138553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 11429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 11489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 1153553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1162bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 1164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 1165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 11665ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko return -1; 1167bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 1169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 11705ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko perror("PIOCSFL"); 11715ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko return -1; 1172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1173bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 1175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 117619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 117719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 117819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 117919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 118019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i); 118119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 118219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_execve); 118319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 118419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork); 118519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 118619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_forkall); 118719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 1188553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1 118919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork1); 119019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 119119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 119219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rfork1); 119319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 119419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 119519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rforkall); 119619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 119719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 119819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 120219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 120319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 120719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 120819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 120919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 121019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 121119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i); 121219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 12139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 121719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 121819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 121919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 122019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 122119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i); 122219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 12239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 1229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg = S_SIG | S_SCE | S_SCX ; 1230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 1231bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1233bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 1243553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT 124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 12459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 12469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1250553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 1251bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 1252bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 1254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1255553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 12589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 12629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 126576989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath if (known_scno(tcp) == SYS_execve) 126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 1269bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 12709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 12719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1272bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1274553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1278bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 1280bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 1281bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 1282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 1283bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1284553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1286bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1288bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1289bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 1290553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (attaching < 2) { 12912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 12922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 12932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 12942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 12952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 12962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 12972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 1298553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 12992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 13002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 13012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 13022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 13032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 13042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 13052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 13062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 13072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 13082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 13092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 13102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 13112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 13122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 13132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 13142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 1315bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1316bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1330bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1332e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb * 133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid) 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1339ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1340ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid && tcp->pid != pid) 134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1349bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1357ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = 0; i < tcbtabsize; i++) { 1358ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1367bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 1375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1376e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->nclone_threads > 0) { 1377e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* There are other threads left in this process, but this 1378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath is the one whose PID represents the whole process. 1379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath We need to keep this record around as a zombie until 1380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath all the threads die. */ 1381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_EXITING; 1382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return; 1383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 1387eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1388e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->parent != NULL) { 1389e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nchildren--; 1390e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD 1391e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_DETACHED) 1392e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_detached--; 1393e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1394e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_threads--; 1395e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif 13960962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED 13970962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath if (!(tcp->flags & TCB_CLONE_DETACHED)) 13980962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif 13990962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath tcp->parent->nzombies++; 1400276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX 1401276ceb33f20fc41403e46684e441230296f6a433Roland McGrath /* Update `tcp->parent->parent->nchildren' and the other fields 1402276ceb33f20fc41403e46684e441230296f6a433Roland McGrath like NCLONE_DETACHED, only for zombie group leader that has 1403276ceb33f20fc41403e46684e441230296f6a433Roland McGrath already reported and been short-circuited at the top of this 1404276ceb33f20fc41403e46684e441230296f6a433Roland McGrath function. The same condition as at the top of DETACH. */ 1405276ceb33f20fc41403e46684e441230296f6a433Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1406276ceb33f20fc41403e46684e441230296f6a433Roland McGrath tcp->parent->nclone_threads == 0 && 1407276ceb33f20fc41403e46684e441230296f6a433Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1408276ceb33f20fc41403e46684e441230296f6a433Roland McGrath droptcb(tcp->parent); 1409276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif 1410e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent = NULL; 1411e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath } 1412e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath 1413e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->flags = 0; 141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 1417bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1418bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 1419bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 1420bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 1421bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1422bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 1423bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1425bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1426553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */ 1427bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 1428e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath rebuild_pollv(); /* Note, flags needs to be cleared by now. */ 142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1431eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1432822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman if (outfname && followfork > 1 && tcp->outf) 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 1434eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1438bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 1452e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1453e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1454e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->parent->nclone_waiting--; 1455e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1457732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) 145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int 14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp) 14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{ 14681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int error = 0; 14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int resumed = 0; 14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* XXX This won't always be quite right (but it never was). 14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath A waiter with argument 0 or < -1 is waiting for any pid in 14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath a particular pgrp, which this child might or might not be 14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath in. The waiter will only wake up if it's argument is -1 14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath or if it's waiting for tcp->pid's pgrp. It makes a 14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath difference to wake up a waiter when there might be more 14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath traced children, because it could get a false ECHILD 14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error. OTOH, if this was the last child in the pgrp, then 14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath it ought to wake up and get ECHILD. We would have to 14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath search the system for all pid's in the pgrp to be sure. 14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && (t->waitpid == -1 || 14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid)) 14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath || (t->waitpid < 0 && t->waitpid == -getpid (t->pid))) 14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath */ 14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && 14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->flags & TCB_SUSPENDED) && 14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) { 14905ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko error = resume(tcp->parent); 14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD 14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && tcp->parent->nclone_waiting > 0) { 14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Some other threads of our parent are waiting too. */ 14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath unsigned int i; 14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Resume all the threads that were waiting for this PID. */ 14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 15011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 15031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid == tcp->pid) { 15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 15061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 15071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (resumed == 0) 15101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Noone was waiting for this PID in particular, 15111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath so now we might need to resume some wildcarders. */ 15121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 15131bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 15141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 15151bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags 15161bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 15171bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 15181bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid <= 0 15191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ) { 15201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 15211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath break; 15221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15253bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif 15261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 15271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath return error; 15281bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath} 15291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 1530bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15320a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig 15330a463880341945df08b6dc79134dc78cc38dc283Roland McGrath Never call DETACH twice on the same process as both unattached and 15340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath attached-unstopped processes give the same ESRCH. For unattached process we 15350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath would SIGSTOP it and wait for its SIGSTOP notification forever. */ 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 1543ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX 15441bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int status, catch_sigstop; 1545a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath struct tcb *zombie = NULL; 1546a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1547a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* If the group leader is lingering only because of this other 1548a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath thread now dying, then detach the leader as well. */ 1549a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1550a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->parent->nclone_threads == 1 && 1551a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1552a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath zombie = tcp->parent; 1553ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif 155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 1556840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab clearbpt(tcp); 155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 15617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * before detaching. Arghh. We go through hoops 15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * to make a clean break of things. 156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 15647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC) 15657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH 15667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH 15677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif 156802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 156902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the 157002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * expected SIGSTOP. We must catch exactly one as otherwise the 157102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * detached process would be left stopped (process state T). 157202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 157302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = (tcp->flags & TCB_STARTUP); 157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 15767bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 15777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (errno != ESRCH) { 15787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath /* Shouldn't happen. */ 15797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: ptrace(PTRACE_DETACH, ...)"); 15807bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 1581134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid 1582134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath : tcp->pid), 1583134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath tcp->pid, 0) < 0) { 15847bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 15857bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: checking sanity"); 15867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 158702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD 158802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ? tcp->parent->pid : tcp->pid), 158902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid, SIGSTOP) < 0) { 15907bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 15917bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: stopping child"); 15927bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 159302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 159402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = 1; 1595ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (catch_sigstop) { 159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno == ECHILD) /* Already gone. */ 16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16017508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != EINVAL) { 160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 16037508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16047508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16057508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */ 16067508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* No __WALL here. */ 16077508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (waitpid(tcp->pid, &status, 0) < 0) { 16087508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) { 16097508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 16107508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16117508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16127508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE 16137508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* If no processes, try clones. */ 16147508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WCLONE, 16157508cb4678141d146d819120f6b5b428c103882eRoland McGrath NULL) < 0) { 16167508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) 16177508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 16187508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16197508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16207508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */ 16217508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16227508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 16247508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 1630732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko ptrace_restart(PTRACE_DETACH, tcp, sig); 163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1633732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_CONT, tcp, 1634eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath WSTOPSIG(status) == SIGTRAP ? 0 1635732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko : WSTOPSIG(status)); 1636732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (error < 0) 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1639ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } 16407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */ 164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 1647732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_DETACH, tcp, sig); 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1650bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 16511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume_from_tcp (tcp); 1652e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 1653e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 1658a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1659a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX 16600a463880341945df08b6dc79134dc78cc38dc283Roland McGrath if (zombie != NULL) { 16610a463880341945df08b6dc79134dc78cc38dc283Roland McGrath /* TCP no longer exists therefore you must not detach () it. */ 16620a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(zombie); 16630a463880341945df08b6dc79134dc78cc38dc283Roland McGrath } 1664a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif 1665a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1669bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1671e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig) 167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1680bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1688ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1689ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 1697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko tprintf(" <unfinished ...>"); 1698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17206d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST 172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 17236d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */ 172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17428f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 17436d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[]; 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 17458f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 17468f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[]; 17478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1768bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1775ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv != NULL) 1776ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath free (pollv); 1777c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1778ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv == NULL) { 177946100d07257824da2ae1147da0324b5788c95501Roland McGrath fprintf(stderr, "%s: out of memory\n", progname); 1780ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath exit(1); 1781ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath } 1782ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 1783ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = j = 0; i < tcbtabsize; i++) { 1784ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 17889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 180910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(proc_poll_pipe[i]) < 0) { 181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1857bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1858bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1859bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 1864a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin _exit(1); 186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 1888a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin _exit(1); 188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1899bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 19005ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 19015ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else 19025ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 19035ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif 19049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 19209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 19379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 19609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 19729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 1973d870b3c31a0139b335a66a829169bacc74624c44John Hughes struct tcb *in_syscall = NULL; 19749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 19799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(0); 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 20069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 20079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 20089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 20099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 2010553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 20119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 20129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 20139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 20149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 20159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 20169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 20179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 20189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 20199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 20209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 20219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 20239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 20249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 20279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2051b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK 20529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 2053b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif 205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 2056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 20579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 2058bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 2059bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 2060bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 2061bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 2062bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 2063bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_STATUS (tcp); 2064bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 20655ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko ioctl_result = IOCTL_WSTOP (tcp); 2066553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 2091553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 21012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 21022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 21032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 21042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman IOCTL (tcp->pfd, PIOCRUN, 0); 21052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 21062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 2107553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2108553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 2114ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab curcol = tcp->curcol; 211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 2120bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 2121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 2122bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 2123bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 2124bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 2125bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 2126bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 2127bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 2128bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 2129553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */ 213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 2132bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 21369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 21379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 2138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 21409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 21419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 21509dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 21519dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 21529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 2160e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 2161e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin && (qual_flags[what] & QUAL_SIGNAL)) { 216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 2164ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 2165ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 21665826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 21675826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 21685826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 21695826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 21705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 2171ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 21725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 21735826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 2177e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAGS_ONLY_STATS 2178e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin && (qual_flags[what] & QUAL_FAULT)) { 217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 2181ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2185bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 21865ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko continue; 2187553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 21899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2193ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab /* Remember current print column before continuing. */ 2194ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = curcol; 21959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 2196553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 21979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 2198553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 2199bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) { 2200553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the 2212e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related clone threads with it. This is called in three circumstances: 2213e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent). 2214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == 0 Continuing TCP will perform an exit_group syscall. 2215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == other Continuing TCP with SIG will kill the process. 2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/ 2217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int 2218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig) 2219e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{ 2220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* We need to locate our records of all the clone threads 2221e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related to TCP, either its children or siblings. */ 22227a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko struct tcb *leader = NULL; 22237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko 22247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (tcp->flags & TCB_CLONE_THREAD) 22257a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko leader = tcp->parent; 22267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko else if (tcp->nclone_detached > 0) 22277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko leader = tcp; 2228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2229e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (sig < 0) { 22307a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (leader != NULL && leader != tcp 22317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko && !(leader->flags & TCB_GROUP_EXITING) 22327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko && !(tcp->flags & TCB_STARTUP) 22337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ) { 2234e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, 2235e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath "PANIC: handle_group_exit: %d leader %d\n", 2236e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->pid, leader ? leader->pid : -1); 22377a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } 22387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko /* TCP no longer exists therefore you must not detach() it. */ 22391bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS 22407a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko resume_from_tcp(tcp); 22411bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif 22420a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(tcp); /* Already died. */ 2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 2245a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* Mark that we are taking the process down. */ 2246a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING; 2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_ATTACHED) { 2248d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath detach(tcp, sig); 22495ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (leader != NULL && leader != tcp) 22501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2251732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else { 2252732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) { 2253732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko cleanup(); 2254732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko return -1; 2255732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2256732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (leader != NULL) { 22570569095472c93c8513edefcf31013503ce4c0589Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2258732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (leader != tcp) 2259732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko droptcb(tcp); 2260732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* The leader will report to us as parent now, 2262e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath and then we'll get to the SIG==-1 case. */ 2263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2266e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath} 2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 2270e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2271eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int 2272eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace() 227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 22802f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 2281eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath static int wait4_options = __WALL; 22822f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif 228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2285eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath while (nprocs != 0) { 2286222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko if (interrupted) 2287eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 2288eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 2289eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 22912f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 2292eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL); 22935bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 22942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 22952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 22962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman errno = 0; 2297eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, wait4_options, 2298eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath cflag ? &ru : NULL); 22992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 23005bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 23012f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 2302eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, __WCLONE, 2303eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath cflag ? &ru : NULL); 2304eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (pid == -1) { 2305eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath fprintf(stderr, "strace: clone wait4 " 23062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman "failed: %s\n", strerror(errno)); 23072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 23082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 2309eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else 2310eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 2311eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */ 231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 2317eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 2318eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 2321eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath switch (wait_errno) { 2322eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case EINTR: 232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2324eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case ECHILD: 232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 2331eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 2332eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath default: 2333eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath errno = wait_errno; 2334eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath perror("strace: wait"); 2335eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return -1; 233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 233810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pid == popen_pid) { 233910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (WIFEXITED(status) || WIFSIGNALED(status)) 234010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin popen_pid = -1; 234110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin continue; 234210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX 234941c48227a86a176da333f713d5047240885f25ccRoland McGrath if (followfork) { 2350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This is needed to go with the CLONE_PTRACE 2351e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath changes in process.c/util.c: we might see 2352e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath the child's initial trap before we see the 2353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent return from the clone syscall. 2354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath Leave the child suspended until the parent 2355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath returns from its system call. Only then 2356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath will we have the association of parent and 2357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath child so that we know how to do clearbpt 2358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in the child. */ 2359418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(pid); 2360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED; 2361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (!qflag) 2362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "\ 2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n", 2364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath pid); 23658b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 2366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else 2367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This can happen if a clone call used 2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath CLONE_PTRACE itself. */ 2369eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif 2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath { 2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "unknown pid: %u\n", pid); 2372e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (WIFSTOPPED(status)) 2373e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2374e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath exit(1); 2375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2377eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* set current output file */ 2378eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath outf = tcp->outf; 2379ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab curcol = tcp->curcol; 238084e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko if (cflag) { 2381eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX 238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 2384eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */ 238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2386eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 2387f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko if (tcp->flags & TCB_SUSPENDED) { 2388f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko /* 2389f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * Apparently, doing any ptrace() call on a stopped 2390f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * process, provokes the kernel to report the process 2391f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * status again on a subsequent wait(), even if the 2392f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * process has not been actually restarted. 2393f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * Since we have inspected the arguments of suspended 2394f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * processes we end up here testing for this case. 2395f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko */ 2396f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko continue; 2397f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko } 239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 2399a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2400a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = 0x100 | WTERMSIG(status); 2401e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 24042efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath tprintf("+++ killed by %s %s+++", 24052efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 24062efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP 24072efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath WCOREDUMP(status) ? "(core dumped) " : 24082efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 24092efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath ""); 2410ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2412e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2413e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2414e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 241576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2416e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 241776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 241876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 241976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 2420a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2421a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = WEXITSTATUS(status); 242276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 24237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status)); 24247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED 24250569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING 24267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING)) 24271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && !(tcp->flags & TCB_GROUP_EXITING) 24280569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif 24297a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ) { 243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 24317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko "PANIC: attached pid %u exited with %d\n", 24327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko pid, WEXITSTATUS(status)); 24337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } 24340a396906981a03f93c07cb912585d0679dd50899Roland McGrath if (tcp == tcp_last) { 24357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL) 24360a396906981a03f93c07cb912585d0679dd50899Roland McGrath tprintf(" <unfinished ... exit status %d>\n", 24370a396906981a03f93c07cb912585d0679dd50899Roland McGrath WEXITSTATUS(status)); 24380a396906981a03f93c07cb912585d0679dd50899Roland McGrath tcp_last = NULL; 24390a396906981a03f93c07cb912585d0679dd50899Roland McGrath } 2440e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2441e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2442e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 244376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2444e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 244776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 2454ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 245602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 245702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Interestingly, the process may stop 245802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * with STOPSIG equal to some other signal 2459eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * than SIGSTOP if we happend to attach 246002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * just before the process takes a signal. 2461c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * A no-MMU vforked child won't send up a signal, 2462c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * so skip the first (lost) execve notification. 246302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 2464c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger if ((tcp->flags & TCB_STARTUP) && 2465c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger (WSTOPSIG(status) == SIGSTOP || strace_vforked)) { 246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 247202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_BPTSET) { 247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 247402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * One example is a breakpoint inherited from 247502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * parent through fork (). 247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2486eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (WSTOPSIG(status) != SIGTRAP) { 248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 249076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 249176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 249376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 2494732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 249876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 249976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2500e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 25021f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil unsigned long addr = 0; 25031f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil long pc = 0; 25049633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO) 25057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# define PSR_RI 41 25067b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman struct siginfo si; 25071f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil long psr; 25087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 2509932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IPSR, &psr); 2510932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IIP, &pc); 25117b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 25127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 25137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman ptrace(PT_GETSIGINFO, pid, 0, (long) &si); 25147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman addr = (unsigned long) si.si_addr; 25153a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO 25163a055d7d64222223da2550ca540043de7e3e232bRoland McGrath if (WSTOPSIG(status) == SIGSEGV || 25173a055d7d64222223da2550ca540043de7e3e232bRoland McGrath WSTOPSIG(status) == SIGBUS) { 25183a055d7d64222223da2550ca540043de7e3e232bRoland McGrath siginfo_t si; 25193a055d7d64222223da2550ca540043de7e3e232bRoland McGrath if (ptrace(PTRACE_GETSIGINFO, pid, 25203a055d7d64222223da2550ca540043de7e3e232bRoland McGrath 0, &si) == 0) 25213a055d7d64222223da2550ca540043de7e3e232bRoland McGrath addr = (unsigned long) 25223a055d7d64222223da2550ca540043de7e3e232bRoland McGrath si.si_addr; 25233a055d7d64222223da2550ca540043de7e3e232bRoland McGrath } 25247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 252576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 25267b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman tprintf("--- %s (%s) @ %lx (%lx) ---", 2527ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WSTOPSIG(status)), 25287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman strsignal(WSTOPSIG(status)), pc, addr); 2529ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 25310569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (((tcp->flags & TCB_ATTACHED) || 25320569095472c93c8513edefcf31013503ce4c0589Roland McGrath tcp->nclone_threads > 0) && 253376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 2534e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2535e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, WSTOPSIG(status)); 2536e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 2538e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 253976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2541732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) { 254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 254802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* we handled the STATUS, we are permitted to interrupt now. */ 254902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 255002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 2551eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) { 2552eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* ptrace() failed in trace_syscall() with ESRCH. 2553eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Likely a result of process disappearing mid-flight. 2554eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Observed case: exit_group() terminating 2555eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * all processes in thread group. In this case, threads 2556eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * "disappear" in an unpredictable moment without any 2557eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * notification to strace via wait(). 2558ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko */ 2559ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (tcp->flags & TCB_ATTACHED) { 2560eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (tcp_last) { 2561eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* Do we have dangling line "syscall(param, param"? 2562eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Finish the line then. We cannot 2563eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath */ 2564eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp_last->flags |= TCB_REPRINT; 2565eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unfinished ...>"); 2566eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath printtrailer(); 2567eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath } 256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2569ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } else { 2570eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath ptrace(PTRACE_KILL, 2571eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->pid, (char *) 1, SIGTERM); 257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 2577e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2578e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_GROUP_EXITING) { 2579e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (handle_group_exit(tcp, 0) < 0) 2580e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 2581e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath continue; 2582e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2583e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 258576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2586732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) { 258776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 259576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 259676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 2598ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab /* Remember current print column before continuing. */ 2599ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = curcol; 2600732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 260576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 260676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2608bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 260976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 261476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 261576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2617e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab va_start(args, fmt); 2618b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (outf) { 2619b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath int n = vfprintf(outf, fmt, args); 2620ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab if (n < 0) { 2621ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab if (outf != stderr) 2622ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab perror(outfname == NULL 2623ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab ? "<writing to pipe>" : outfname); 2624ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab } else 2625b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath curcol += n; 2626b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath } 262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 2632eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathprintleader(tcp) 2633eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstruct tcb *tcp; 263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 2635732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last) { 2636eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (tcp_last->ptrace_errno) { 2637732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last->flags & TCB_INSYSCALL) { 2638eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unavailable>)"); 2639eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tabto(acolumn); 2640732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2641eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf("= ? <unavailable>\n"); 2642eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp_last->ptrace_errno = 0; 2643732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else if (!outfname || followfork < 2 || tcp_last == tcp) { 26447e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tcp_last->flags |= TCB_REPRINT; 2645eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unfinished ...>\n"); 2646732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 264876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 268776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 268876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 269076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 269176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 2693ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void) 269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 269576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 26989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2699ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 27009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2701ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint 2702ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size) 2703ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{ 27049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 27059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 2706553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 27079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 27089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 27099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 27109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 27119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 27129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 27139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 2714553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 2715ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko return writev(fd, iov, n); 27169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 27179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 27189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2719