strace.c revision 7e0615f3aecc023e2756a83bdf113c5ceaac431d
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> 437e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko#include <sys/utsname.h> 4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h> 4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h> 4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h> 4719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h> 4870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h> 4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX 51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h> 52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill 53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig)) 54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill 55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig)) 56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else 57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath /* kill() may choose arbitrarily the target task of the process group 58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath while we later wait on a that specific TID. PID process waits become 59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath TID task specific waits for a process under ptrace(2). */ 60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!" 61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) kill ((tid), (sig)) 62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif 63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif 64134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath 657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX) 667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 687b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h> 71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 72bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 75ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H 779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 801d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif 8196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ; 82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind; 83418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg; 8496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko 8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8641c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0; 87b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0; 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 1037e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenkostatic struct utsname utsname_buf; 1047e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko 10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0; 10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 108a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0; 109a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0; 11096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic int ptrace_stop_sig = SIGTRAP; 11196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic bool ptrace_opts_set; 112a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin 113b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL; 11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 119b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL; 12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 121ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab; 122ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize; 12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname; 12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1250a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig)); 12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void)); 12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void)); 12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig)); 12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */ 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted; 13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */ 13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd)); 14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig)); 14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void)); 146ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv; 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void)); 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd)); 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 179de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 180ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 181de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 197ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\ 19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 202de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 203de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it 20417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 205de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath */ 206de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd) 22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int flags, newflags; 22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((flags = fcntl(fd, F_GETFD, 0)) < 0) 22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_GETFD: %s\n", 22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newflags = flags | FD_CLOEXEC; 23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (flags == newflags) 23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fcntl(fd, F_SETFD, newflags) < 0) 23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_SETFD: %s\n", 23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids 24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations. 24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void 25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void) 25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4 25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int euid = geteuid(), uid = getuid(); 25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (euid != uid && setreuid(euid, uid) < 0) 25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: setreuid: %s\n", 25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin exit(1); 26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 2644bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE 2654bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64 2664bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else 2674bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen 2684bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif 2694bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath 27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 27110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode) 27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 2764bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath if ((fp = fopen_for_output(path, mode)) == NULL) 27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: can't fopen '%s': %s\n", 27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, path, strerror(errno)); 27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fp && set_cloexec_flag(fileno(fp)) < 0) 28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fclose(fp); 28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fp = NULL; 28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fp; 28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1; 28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL 29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh" 29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish 29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3) 29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid. 29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command) 30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int fds[2]; 30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pipe(fds) < 0) 30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: pipe: %s\n", 30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(fds[1]) < 0) 31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((popen_pid = fork()) == -1) 32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fork: %s\n", 32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (popen_pid) 33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* parent */ 33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fdopen(fds[1], "w"); 33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } else 33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* child */ 34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fds[0] && (dup2(fds[0], 0) || close(fds[0]))) 34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: dup2: %s\n", 34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin execl(_PATH_BSHELL, "sh", "-c", command, NULL); 34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: execl: %s: %s\n", 34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, _PATH_BSHELL, strerror(errno)); 35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp) 35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (outfname && followfork > 1) { 35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin char name[MAXPATHLEN]; 35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin sprintf(name, "%s.%u", outfname, tcp->pid); 36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((fp = strace_fopen(name, "w")) == NULL) 36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin tcp->outf = fp; 36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void) 37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tcbi; 37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Block user interruptions as we would leave the traced 37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * process stopped (process state T) if we would terminate in 37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * between PTRACE_ATTACH and wait4 () on SIGSTOP. 37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * We rely on cleanup () from this point on. 38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 384ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 385ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid_t pid = fork(); 386ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(1); 388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid) { /* parent */ 390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Wait for child to attach to straced process 392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * (our parent). Child SIGKILLs us after it attached. 393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Parent's wait() is unblocked by our death, 394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * it proceeds to exec the straced program. 395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pause(); 397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(0); /* paranoia */ 398ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 399ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 400ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = tcbtab[tcbi]; 40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX 40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif 40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Reinitialize the output since it may have changed. */ 41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->outf = outf; 41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (newoutf(tcp) < 0) 41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (proc_open(tcp, 1) < 0) { 41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "trouble opening proc file\n"); 41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX 422ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (followfork && !daemonized_tracer) { 42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char procdir[MAXPATHLEN]; 42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath DIR *dir; 42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath dir = opendir(procdir); 42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (dir != NULL) { 42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath unsigned int ntid = 0, nerr = 0; 43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct dirent *de; 43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tid; 43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath while ((de = readdir(dir)) != NULL) { 43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (de->d_fileno == 0 || 43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath de->d_name[0] == '.') 43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tid = atoi(de->d_name); 43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tid <= 0) 43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++ntid; 44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tid, 44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (char *) 1, 0) < 0) 44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++nerr; 44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (tid != tcbtab[tcbi]->pid) { 444418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(tid); 44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK; 44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nchildren++; 44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_threads++; 44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_detached++; 44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->parent = tcbtab[tcbi]; 45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) { 45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return; 45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath closedir(dir); 45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (nerr == ntid) { 46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) { 46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ntid -= nerr; 46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ntid > 1) 46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "\ 46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached with %u threads - interrupt to quit\n", 46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid, ntid); 47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "\ 47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached - interrupt to quit\n", 47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif 47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* INTERRUPTED is going to be checked at the top of TRACE. */ 485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It is our grandparent we trace, not a -p PID. 489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Don't want to just detach on exit, so... 490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags &= ~TCB_ATTACHED; 492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make parent go away. 494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Also makes grandparent's wait() unblock. 495ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 496ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(getppid(), SIGKILL); 497ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 498ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) 50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, 50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath "Process %u attached - interrupt to quit\n", 50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv) 51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct stat statbuf; 51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath const char *filename; 51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char pathname[MAXPATHLEN]; 51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int pid = 0; 51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath filename = argv[0]; 52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(filename, '/')) { 52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath errno = ENAMETOOLONG; 52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC 52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Debuggers customarily check the current directory 53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * first regardless of the path but doing that gives 53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * security geeks a panic attack. 53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (stat(filename, &statbuf) == 0) 53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */ 53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char *path; 53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int m, n, len; 54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (path = getenv("PATH"); path && *path; path += m) { 54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(path, ':')) { 54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath n = strchr(path, ':') - path; 54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n + 1; 54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n = strlen(path); 54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (n == 0) { 54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!getcwd(pathname, MAXPATHLEN)) 55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = strlen(pathname); 55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (n > sizeof pathname - 1) 55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strncpy(pathname, path, n); 55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = n; 55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (len && pathname[len - 1] != '/') 56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pathname[len++] = '/'; 56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname + len, filename); 56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) == 0 && 56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Accept only regular files 56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath with some execute bits set. 56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath XXX not perfect, might still fail */ 56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath S_ISREG(statbuf.st_mode) && 56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (statbuf.st_mode & 0111)) 56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) < 0) { 57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "%s: %s: command not found\n", 57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath progname, filename); 57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 576a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin strace_child = pid = fork(); 577ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: fork"); 57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath cleanup(); 58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 581ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 582ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */ 583ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */ 584ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko ) { 585ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid = getpid(); 58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf != stderr) close (fileno (outf)); 58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS 58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Kludge for SGI, see proc_open for details. */ 59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_handler = foobar; 59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_flags = 0; 59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigemptyset(&sa.sa_mask); 59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigaction(SIGINT, &sa, NULL); 59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */ 59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD 59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pause(); 59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */ 598ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); /* stop HERE */ 59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */ 60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf!=stderr) 60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath close(fileno (outf)); 60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko perror("strace: ptrace(PTRACE_TRACEME, ...)"); 607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko exit(1); 608ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 609ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (debug) 610ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); 61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL || geteuid() == 0) { 61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath uid_t run_euid = run_uid; 61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath gid_t run_egid = run_gid; 61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISUID) 61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_euid = statbuf.st_uid; 61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISGID) 62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_egid = statbuf.st_gid; 62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * It is important to set groups before we 62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * lose privileges on setuid. 62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL) { 62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (initgroups(username, run_gid) < 0) { 62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("initgroups"); 62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setregid(run_gid, run_egid) < 0) { 63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setregid"); 63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setreuid(run_uid, run_euid) < 0) { 63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setreuid"); 63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath setreuid(run_uid, run_uid); 64302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Induce an immediate stop so that the parent 647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will resume us with PTRACE_SYSCALL and display 648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * this execve call normally. 649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 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 7027e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko uname(&utsname_buf); 7037e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko 704ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 705ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 706418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) { 70708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 70808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 70908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 710418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) { 71108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 71208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 71308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 714ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp) 715ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]]; 716ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 719138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_sortby(DEFAULT_SORTBY); 720138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_personality(DEFAULT_PERSONALITY); 72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "+cdfFhiqrtTvVxz" 727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 728ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "D" 729ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 730ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "a:e:o:O:p:s:S:u:E:")) != EOF) { 73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cflag++; 73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 739ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 740ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* Experimental, not documented in manpage yet. */ 741ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko case 'D': 742ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko daemonized_tracer = 1; 743ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko break; 744ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 74541c48227a86a176da333f713d5047240885f25ccRoland McGrath case 'F': 74606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin optF = 1; 74706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin break; 74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 7779c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 78017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 78117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 78217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 796de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if ((pid = atoi(optarg)) <= 0) { 79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 80254a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 805418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloc_tcb(pid, 0); 80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 811dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath if (max_strlen < 0) { 812dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath fprintf(stderr, 813dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath "%s: invalid -s argument: %s\n", 814dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath progname, optarg); 815dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath exit(1); 816dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath } 81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 824de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 825de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if (putenv(optarg) < 0) { 826de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 827de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath progname); 828de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath exit(1); 829de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath } 830de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 837d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath if ((optind == argc) == !pflag_seen) 838ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 839ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 84006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin if (!followfork) 84106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin followfork = optF; 84206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin 843cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath if (followfork > 1 && cflag) { 844cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath fprintf(stderr, 845cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath "%s: -c and -ff are mutually exclusive options\n", 846cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath progname); 847cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath exit(1); 848cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath } 849cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath 85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 86209553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath progname, username); 86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 87537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 87637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 87737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 87837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 87937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 88037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 88137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (followfork > 1) { 88237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath fprintf(stderr, "\ 88337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n", 88437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath progname); 88537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 88637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 88737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath 88810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((outf = strace_popen(outfname + 1)) == NULL) 88937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 89054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 89110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin else if (followfork <= 1 && 89210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin (outf = strace_fopen(outfname, "w")) == NULL) 89354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 89637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (!outfname || outfname[0] == '|' || outfname[0] == '!') 89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 89837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname && optind < argc) { 89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 901369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 90254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* Valid states here: 90354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath optind < argc pflag_seen outfname interactive 90454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 0 1 90554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 0 1 90654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 1 0 90754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 1 1 90854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath */ 90954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 91054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* STARTUP_CHILD must be called before the signal handlers get 91154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath installed below as they are inherited into the spawned process. 91254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath Also we do not need to be protected by them as during interruption 91354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath in the STARTUP_CHILD mode we kill the spawned process anyway. */ 91454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath if (!pflag_seen) 91554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath startup_child(&argv[optind]); 91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 941bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 944553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 945553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath /* Make sure SIGCHLD has the default action so that waitpid 946553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath definitely works without losing track of children. The user 947553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath should not have given us a bogus state to inherit, but he might 948553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath have. Arguably we should detect SIG_IGN here and pass it on 949553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath to children, but probably noone really needs that. */ 950553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sa.sa_handler = SIG_DFL; 951553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sigaction(SIGCHLD, &sa, NULL); 952bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 954ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pflag_seen || daemonized_tracer) 95502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_attach(); 95602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 960a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin fflush(NULL); 961a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (exit_code > 0xff) { 962a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Child was killed by a signal, mimic that. */ 963a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code &= 0xff; 964a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin signal(exit_code, SIG_DFL); 965a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin raise(exit_code); 966a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Paranoia - what if this signal is not fatal? 967a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin Exit with 128 + signo then. */ 968a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code += 128; 969a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin } 970a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit(exit_code); 97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 973418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid 974418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void) 9757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{ 9767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath /* Allocate some more TCBs and expand the table. 9777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath We don't want to relocate the TCBs because our 9787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath callers have pointers and it would be a pain. 9797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath So tcbtab is a table of pointers. Since we never 9807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free the TCBs, we allocate a single chunk of many. */ 9817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb **newtab = (struct tcb **) 9827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]); 9837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize, 9847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath sizeof *newtcbs); 9857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath int i; 9867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab == NULL || newtcbs == NULL) { 98776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin fprintf(stderr, "%s: expand_tcbtab: out of memory\n", 98876860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin progname); 989418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko cleanup(); 990418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko exit(1); 9917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath } 9927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath for (i = tcbtabsize; i < 2 * tcbtabsize; ++i) 9937b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath newtab[i] = &newtcbs[i - tcbtabsize]; 9947b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtabsize *= 2; 9957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtab = newtab; 9967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath} 9977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 99910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed) 100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1004418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if (nprocs == tcbtabsize) 1005418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko expand_tcbtab(); 1006418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko 1007ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1008ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 10107e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko memset(tcp, 0, sizeof(*tcp)); 101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 101610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (command_options_parsed) 101710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newoutf(tcp); 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1021418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko fprintf(stderr, "%s: bug in alloc_tcb\n", progname); 1022418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko cleanup(); 1023418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko exit(1); 102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1026bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 1028418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching) 102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 1032bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 103319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 103419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 1037bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1042ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 10439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 10449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 10459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 10469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 10479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 104910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 10509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 10539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 10549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 10559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 105710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_stat) < 0) { 10589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 10619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 106510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_as) < 0) { 10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 1070bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) { 1073bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1074bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 1075bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR)) < 0) { 1076bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 108010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 10819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 10829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 10839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 1084bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1085bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 1086bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 1087bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 1088bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 1093bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1095bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1096bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1097bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1098bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 11069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 11109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 1111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman break; 111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 111616a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1120553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 11249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 11309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 1135553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1144bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 1146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 1148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1149bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1150bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 1151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 1152bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCSFL"); 1153bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1154bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1155bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 1157bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 115819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 115919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 116019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 116119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 116219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i); 116319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 116419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_execve); 116519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 116619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork); 116719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 116819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_forkall); 116919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 1170553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1 117119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork1); 117219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 117319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 117419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rfork1); 117519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 117619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 117719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rforkall); 117819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 117919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 118019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 118419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 118519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 118919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 119019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 119119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 119219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 119319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i); 119419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 11959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 119919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 120019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 120119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 120219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 120319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i); 120419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 12059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1210bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 1211bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg = S_SIG | S_SCE | S_SCX ; 1212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 1213bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 1214bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1215bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1216bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 1225553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT 122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 12279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 12289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1232553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 1233bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 1234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1235bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 1236bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1237553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 12409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 12449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 1245bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 1246bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 124776989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath if (known_scno(tcp) == SYS_execve) 124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 1251bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 12529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 12539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1255bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1256553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1260bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 1265bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1266553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1268bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1270bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1271bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 1272553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (attaching < 2) { 12732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 12742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 12752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 12762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 12772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 12782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 12792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 1280553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 12812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 12822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 12832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 12842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 12852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 12862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 12872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 12882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 12892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 12902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 12912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 12922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 12932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 12942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 12952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 12962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 1297bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1298bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1312bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb * 131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid) 131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1321ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1322ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid && tcp->pid != pid) 132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1331bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1339ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = 0; i < tcbtabsize; i++) { 1340ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 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#endif /* USE_PROCFS */ 135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 1357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->nclone_threads > 0) { 1359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* There are other threads left in this process, but this 1360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath is the one whose PID represents the whole process. 1361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath We need to keep this record around as a zombie until 1362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath all the threads die. */ 1363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_EXITING; 1364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return; 1365e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 1369eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1370e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->parent != NULL) { 1371e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nchildren--; 1372e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD 1373e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_DETACHED) 1374e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_detached--; 1375e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1376e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_threads--; 1377e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif 13780962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED 13790962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath if (!(tcp->flags & TCB_CLONE_DETACHED)) 13800962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif 13810962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath tcp->parent->nzombies++; 1382276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX 1383276ceb33f20fc41403e46684e441230296f6a433Roland McGrath /* Update `tcp->parent->parent->nchildren' and the other fields 1384276ceb33f20fc41403e46684e441230296f6a433Roland McGrath like NCLONE_DETACHED, only for zombie group leader that has 1385276ceb33f20fc41403e46684e441230296f6a433Roland McGrath already reported and been short-circuited at the top of this 1386276ceb33f20fc41403e46684e441230296f6a433Roland McGrath function. The same condition as at the top of DETACH. */ 1387276ceb33f20fc41403e46684e441230296f6a433Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1388276ceb33f20fc41403e46684e441230296f6a433Roland McGrath tcp->parent->nclone_threads == 0 && 1389276ceb33f20fc41403e46684e441230296f6a433Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1390276ceb33f20fc41403e46684e441230296f6a433Roland McGrath droptcb(tcp->parent); 1391276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif 1392e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent = NULL; 1393e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath } 1394e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath 1395e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->flags = 0; 139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 1399bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1400bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 1401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 1402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 1403bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1404bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 1405bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 1406bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1407bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1408553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */ 1409bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 1410e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath rebuild_pollv(); /* Note, flags needs to be cleared by now. */ 141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1413eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1414822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman if (outfname && followfork > 1 && tcp->outf) 141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 1416eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1420bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 1434e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1435e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1436e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->parent->nclone_waiting--; 1437e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1439732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14471bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int 14481bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp) 14491bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{ 14501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int error = 0; 14511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int resumed = 0; 14521bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* XXX This won't always be quite right (but it never was). 14541bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath A waiter with argument 0 or < -1 is waiting for any pid in 14551bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath a particular pgrp, which this child might or might not be 14561bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath in. The waiter will only wake up if it's argument is -1 14571bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath or if it's waiting for tcp->pid's pgrp. It makes a 14581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath difference to wake up a waiter when there might be more 14591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath traced children, because it could get a false ECHILD 14601bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error. OTOH, if this was the last child in the pgrp, then 14611bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath it ought to wake up and get ECHILD. We would have to 14621bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath search the system for all pid's in the pgrp to be sure. 14631bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14641bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && (t->waitpid == -1 || 14651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid)) 14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath || (t->waitpid < 0 && t->waitpid == -getpid (t->pid))) 14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath */ 14681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && 14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->flags & TCB_SUSPENDED) && 14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) { 14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error = resume(tcp->parent); 14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD 14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && tcp->parent->nclone_waiting > 0) { 14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Some other threads of our parent are waiting too. */ 14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath unsigned int i; 14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Resume all the threads that were waiting for this PID. */ 14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid == tcp->pid) { 14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (resumed == 0) 14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Noone was waiting for this PID in particular, 14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath so now we might need to resume some wildcarders. */ 14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags 14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid <= 0 15011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ) { 15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 15031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath break; 15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 15081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath return error; 15091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath} 15101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif 15111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 1512bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15140a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig 15150a463880341945df08b6dc79134dc78cc38dc283Roland McGrath Never call DETACH twice on the same process as both unattached and 15160a463880341945df08b6dc79134dc78cc38dc283Roland McGrath attached-unstopped processes give the same ESRCH. For unattached process we 15170a463880341945df08b6dc79134dc78cc38dc283Roland McGrath would SIGSTOP it and wait for its SIGSTOP notification forever. */ 151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 1525ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX 15261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int status, catch_sigstop; 1527a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath struct tcb *zombie = NULL; 1528a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1529a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* If the group leader is lingering only because of this other 1530a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath thread now dying, then detach the leader as well. */ 1531a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1532a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->parent->nclone_threads == 1 && 1533a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1534a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath zombie = tcp->parent; 1535ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = SIGKILL; 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 15437bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * before detaching. Arghh. We go through hoops 15447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * to make a clean break of things. 154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 15467bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC) 15477bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH 15487bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH 15497bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif 155002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 155102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the 155202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * expected SIGSTOP. We must catch exactly one as otherwise the 155302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * detached process would be left stopped (process state T). 155402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 155502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = (tcp->flags & TCB_STARTUP); 155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 15587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 15597bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (errno != ESRCH) { 15607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath /* Shouldn't happen. */ 15617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: ptrace(PTRACE_DETACH, ...)"); 15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 1563134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid 1564134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath : tcp->pid), 1565134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath tcp->pid, 0) < 0) { 15667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 15677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: checking sanity"); 15687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 156902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD 157002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ? tcp->parent->pid : tcp->pid), 157102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid, SIGSTOP) < 0) { 15727bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 15737bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: stopping child"); 15747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 157502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 157602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = 1; 1577ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (catch_sigstop) { 157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 15797508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 15807508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 15817508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno == ECHILD) /* Already gone. */ 15827508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 15837508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != EINVAL) { 158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 15857508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 15867508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 15877508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */ 15887508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* No __WALL here. */ 15897508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (waitpid(tcp->pid, &status, 0) < 0) { 15907508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) { 15917508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 15927508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 15937508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 15947508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE 15957508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* If no processes, try clones. */ 15967508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WCLONE, 15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath NULL) < 0) { 15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) 15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16017508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16027508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */ 16037508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16047508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 16067508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif 160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 1612732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko ptrace_restart(PTRACE_DETACH, tcp, sig); 161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1615732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_CONT, tcp, 161696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko WSTOPSIG(status) == ptrace_stop_sig ? 0 1617732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko : WSTOPSIG(status)); 1618732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (error < 0) 161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1621ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } 16227bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */ 162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 1629732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_DETACH, tcp, sig); 163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1632bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 16331bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume_from_tcp (tcp); 1634e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 1635e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 1640a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1641a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX 16420a463880341945df08b6dc79134dc78cc38dc283Roland McGrath if (zombie != NULL) { 16430a463880341945df08b6dc79134dc78cc38dc283Roland McGrath /* TCP no longer exists therefore you must not detach () it. */ 16440a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(zombie); 16450a463880341945df08b6dc79134dc78cc38dc283Roland McGrath } 1646a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif 1647a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1651bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig) 165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(pid); 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp) 166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1671bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1679ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1680ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 1688ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko tprintf(" <unfinished ...>"); 1689ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17116d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST 171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 17146d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */ 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17338f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 17346d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[]; 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 17368f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 17378f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[]; 17388f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1759bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1766ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv != NULL) 1767ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath free (pollv); 1768c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1769ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv == NULL) { 177046100d07257824da2ae1147da0324b5788c95501Roland McGrath fprintf(stderr, "%s: out of memory\n", progname); 1771ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath exit(1); 1772ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath } 1773ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 1774ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = j = 0; i < tcbtabsize; i++) { 1775ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 17799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 180010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(proc_poll_pipe[i]) < 0) { 180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1848bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1849bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1850bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 1855a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin _exit(1); 185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 1879a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin _exit(1); 188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1890bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 1891bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 1892bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1893bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 1894bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 18959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 19119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 19289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 19519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 19639dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 1964d870b3c31a0139b335a66a829169bacc74624c44John Hughes struct tcb *in_syscall = NULL; 19659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 19709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(0); 198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 19979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 19989dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 19999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 20009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 2001553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 20029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 20039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 20049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 20059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 20069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 20079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 20089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 20099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 20109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 20119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 20129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 20149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 20159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 20189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2042b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK 20439dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 2044b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif 204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 2047bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 20489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 2049bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 2050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 2051bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 2052bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 2053bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 2054bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_STATUS (tcp); 2055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 2056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 2057553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2080bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2081bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 2082553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 20922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 20932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 20942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 20952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman IOCTL (tcp->pfd, PIOCRUN, 0); 20962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 20972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 2098553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2099553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 2108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 2110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 2111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 2112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 2113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 2114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 2115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 2116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 2117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 2119553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */ 212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 2122bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 21269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 21279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 2128bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 21309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 21319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 21409dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 21419dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 21429dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) { 215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 2153ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 2154ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 21555826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 21565826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 21575826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 21585826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 21595826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 2160ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 21615826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 21625826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_FAULT)) { 216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 2169ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2173bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 2174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman continue; 2175553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 21779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 21819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 2182553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 21839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 2184553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 2185bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) { 2186553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2194bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2196e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2197e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the 2198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related clone threads with it. This is called in three circumstances: 2199e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent). 2200e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == 0 Continuing TCP will perform an exit_group syscall. 2201e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == other Continuing TCP with SIG will kill the process. 2202e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/ 2203e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int 2204e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig) 2205e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{ 2206e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* We need to locate our records of all the clone threads 2207e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related to TCP, either its children or siblings. */ 2208e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD) 2209e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ? tcp->parent 2210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath : tcp->nclone_detached > 0 2211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ? tcp : NULL); 2212e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2213e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (sig < 0) { 22140569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (leader != NULL && leader != tcp && 22150569095472c93c8513edefcf31013503ce4c0589Roland McGrath !(leader->flags & TCB_GROUP_EXITING)) 2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, 2217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath "PANIC: handle_group_exit: %d leader %d\n", 2218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->pid, leader ? leader->pid : -1); 22190a463880341945df08b6dc79134dc78cc38dc283Roland McGrath /* TCP no longer exists therefore you must not detach () it. */ 22201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS 22211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath resume_from_tcp (tcp); 22221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif 22230a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(tcp); /* Already died. */ 2224e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2225e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 2226a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* Mark that we are taking the process down. */ 2227a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING; 2228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_ATTACHED) { 2229d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath detach(tcp, sig); 22301bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (leader != NULL && leader != tcp) 22311bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2232732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else { 2233732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) { 2234732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko cleanup(); 2235732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko return -1; 2236732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2237732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (leader != NULL) { 22380569095472c93c8513edefcf31013503ce4c0589Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2239732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (leader != tcp) 2240732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko droptcb(tcp); 2241732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2242e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* The leader will report to us as parent now, 2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath and then we'll get to the SIG==-1 case. */ 2244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2248e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath} 2250e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 2251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2252215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic struct tcb * 2253215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkocollect_stopped_tcbs(void) 225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 225547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko#ifdef LINUX 225647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko static int remembered_pid; 225747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko static int remembered_status; 225847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko#endif 225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 226347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko struct tcb *found_tcps; 226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 226547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko struct tcb **nextp; 226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 2267215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko struct rusage* ru_ptr = cflag ? &ru : NULL; 2268215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko int wnohang = 0; 22692f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 2270215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko int wait4_options = __WALL; 22712f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif 227247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko 227347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko if (remembered_pid > 0) { 227447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko pid = remembered_pid; 227547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko remembered_pid = 0; 227647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko if (debug) 227747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko fprintf(stderr, " [remembered wait(%#x) = %u]\n", 227847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko remembered_status, pid); 227947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko tcp = pid2tcb(pid); /* can't be NULL */ 228047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko tcp->wait_status = remembered_status; 228147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko tcp->next_need_service = NULL; 228247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko return tcp; 228347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko } 228447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko nextp = &found_tcps; 228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 228747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko found_tcps = NULL; 2288215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko while (1) { 228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 22902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 2291215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr); 22925bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 22932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 22942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 22952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman errno = 0; 2296215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr); 22972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 22985bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 22992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 2300215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr); 2301215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko if (pid < 0 && errno != ECHILD) { 2302215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko fprintf(stderr, "strace: wait4(WCLONE) " 23032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman "failed: %s\n", strerror(errno)); 23042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 23052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 2306215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#else /* !__WALL */ 2307215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko pid = wait4(-1, &status, wnohang, ru_ptr); 2308215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif 230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2317215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko if (pid == 0 && wnohang) { 2318215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko /* We had at least one successful 2319215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * wait() before. We waited 2320215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * with WNOHANG second time. 2321215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * Stop collecting more tracees, 2322215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * process what we already have. 2323215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko */ 2324215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko break; 2325215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko } 232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 23272c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko if (wait_errno == EINTR) 232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 23292c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko if (wait_errno == ECHILD) { 233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 23372c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko if (nprocs != 0) { 23382c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko fprintf(stderr, "strace: proc miscount\n"); 23392c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko exit(1); 23402c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko } 234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 23422c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko break; 234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 23442c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko errno = wait_errno; 23452c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko perror("strace: wait"); 23462c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko exit(1); 234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 234810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pid == popen_pid) { 234910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (WIFEXITED(status) || WIFSIGNALED(status)) 235010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin popen_pid = -1; 235110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin continue; 235210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 235647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko /* RHEL5 bug workaround. 235747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * It can re-report stopped tasks. Happens on SIGSTOPs here. 235847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * Second (bogus) report has signal# set to 0. 235947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * Stop collecting and process what we have. 236047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko */ 236147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko if (WIFSTOPPED(status) && WSTOPSIG(status) == 0) 236247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko break; 236347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko 236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 2366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX 236741c48227a86a176da333f713d5047240885f25ccRoland McGrath if (followfork) { 2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This is needed to go with the CLONE_PTRACE 2369e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath changes in process.c/util.c: we might see 2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath the child's initial trap before we see the 2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent return from the clone syscall. 2372e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath Leave the child suspended until the parent 2373e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath returns from its system call. Only then 2374e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath will we have the association of parent and 2375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath child so that we know how to do clearbpt 2376e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in the child. */ 2377418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(pid); 2378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED; 2379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (!qflag) 2380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "\ 2381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n", 2382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath pid); 23838b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 2384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else 2385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This can happen if a clone call used 2386e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath CLONE_PTRACE itself. */ 2387215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif /* LINUX */ 2388e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath { 2389e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "unknown pid: %u\n", pid); 2390e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (WIFSTOPPED(status)) 2391e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2392e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath exit(1); 2393e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2395215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 2400215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif 240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2402f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko if (tcp->flags & TCB_SUSPENDED) { 2403f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko /* 2404f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * Apparently, doing any ptrace() call on a stopped 2405f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * process, provokes the kernel to report the process 2406f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * status again on a subsequent wait(), even if the 2407f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * process has not been actually restarted. 2408f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * Since we have inspected the arguments of suspended 2409f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * processes we end up here testing for this case. 241047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * 241147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * We also end up here when we catch new pid of 241247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * CLONE_PTRACEd process. Do not process/restart it 241347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * until we see corresponding clone() syscall exit 241447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * in its parent. 2415f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko */ 2416f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko continue; 2417f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko } 2418f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko 2419215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#ifdef LINUX 242047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko /* So far observed only on RHEL5 ia64, but I imagine this 242147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * can legitimately happen elsewhere. 242247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * If we waited and got a stopped task notification, 242347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * subsequent wait may return the same pid again, for example, 242447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * with SIGKILL notification. SIGKILL kills even stopped tasks. 242547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * We must not add it to the list 242647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko * (one task can't be inserted twice in the list). 242747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko */ 242847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko { 242947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko struct tcb *f = found_tcps; 243047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko while (f) { 243147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko if (f == tcp) { 243247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko remembered_pid = pid; 243347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko remembered_status = status; 243447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko return found_tcps; 243547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko } 243647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko f = f->next_need_service; 243747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko } 243847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko } 2439f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko /* It is important to not invert the order of tasks 2440f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * to process. For one, alloc_tcb() above picks newly forked 2441f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * threads in some order, processing of them and their parent 2442f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * should be in the same order, otherwise bad things happen 2443f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * (misinterpreted SIGSTOPs and such). 2444f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko */ 244547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko tcp->wait_status = status; 2446f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko *nextp = tcp; 2447f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko nextp = &tcp->next_need_service; 244847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko *nextp = NULL; 2449215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko wnohang = WNOHANG; 2450215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif 2451215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#ifdef SUNOS4 2452215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko /* Probably need to replace wait with waitpid 2453215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * and loop on Sun too, but I can't test it. Volunteers? 2454215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko */ 245547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko tcp->wait_status = status; 245647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko tcp->next_need_service = NULL; 245747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko found_tcps = tcp; 2458215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko break; 2459215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif 246047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko } /* while (1) - collecting all stopped/exited tracees */ 2461215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 2462f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko return found_tcps; 2463215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko} 2464215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 2465215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic int 2466215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkohandle_stopped_tcbs(struct tcb *tcp) 2467215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko{ 2468215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko for (; tcp; tcp = tcp->next_need_service) { 2469215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko int pid; 2470215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko int status; 247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2472215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko outf = tcp->outf; 2473215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko status = tcp->wait_status; 2474215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko pid = tcp->pid; 2475215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 2477a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2478a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = 0x100 | WTERMSIG(status); 247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 24822efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath tprintf("+++ killed by %s %s+++", 24832efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 24842efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP 24852efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath WCOREDUMP(status) ? "(core dumped) " : 24862efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 24872efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath ""); 2488ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2491e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2492e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 249376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2494e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 2498a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2499a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = WEXITSTATUS(status); 250076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u exited\n", pid); 25020569095472c93c8513edefcf31013503ce4c0589Roland McGrath if ((tcp->flags & TCB_ATTACHED) 25030569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING 25040569095472c93c8513edefcf31013503ce4c0589Roland McGrath && !(tcp->parent && (tcp->parent->flags & 25050569095472c93c8513edefcf31013503ce4c0589Roland McGrath TCB_GROUP_EXITING)) 25061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && !(tcp->flags & TCB_GROUP_EXITING) 25070569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif 25080569095472c93c8513edefcf31013503ce4c0589Roland McGrath ) 250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "PANIC: attached pid %u exited\n", 251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 25120a396906981a03f93c07cb912585d0679dd50899Roland McGrath if (tcp == tcp_last) { 25130a396906981a03f93c07cb912585d0679dd50899Roland McGrath if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) 25140a396906981a03f93c07cb912585d0679dd50899Roland McGrath == TCB_INSYSCALL) 25150a396906981a03f93c07cb912585d0679dd50899Roland McGrath tprintf(" <unfinished ... exit status %d>\n", 25160a396906981a03f93c07cb912585d0679dd50899Roland McGrath WEXITSTATUS(status)); 25170a396906981a03f93c07cb912585d0679dd50899Roland McGrath tcp_last = NULL; 25180a396906981a03f93c07cb912585d0679dd50899Roland McGrath } 2519e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2520e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2521e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 252276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2523e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 252576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 252676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 252776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 253176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 253276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 2533ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 253476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 253502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 253602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Interestingly, the process may stop 253702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * with STOPSIG equal to some other signal 253802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * than SIGSTOP if we happend to attach 253902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * just before the process takes a signal. 254002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 254102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) { 254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 254802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_BPTSET) { 254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 255002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * One example is a breakpoint inherited from 255102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * parent through fork (). 255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 255376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 255576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 255776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 255876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2559b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko/* Add more OSes after you verified it works for them. */ 2560f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko/* PTRACE_SETOPTIONS may be an enum, not a #define. 2561f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko * But sometimes we can test for it by checking PT_SETOPTIONS. 2562f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko */ 2563f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS) 25640861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_O_TRACESYSGOOD 25650861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# define PTRACE_O_TRACESYSGOOD 0x00000001 25660861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif 25670861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_O_TRACEEXEC 25680861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# define PTRACE_O_TRACEEXEC 0x00000010 25690861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif 25700861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_EVENT_EXEC 25710861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# define PTRACE_EVENT_EXEC 4 25720861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif 25731e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko /* 25741e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * Ask kernel to set signo to SIGTRAP | 0x80 25751e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * on ptrace-generated SIGTRAPs, and mark 25761e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * execve's SIGTRAP with PTRACE_EVENT_EXEC. 25771e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko */ 257896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko if (!ptrace_opts_set) { 25797e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko char *p; 258096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko ptrace_opts_set = 1; 25817e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko 25827e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko /* RHEL 2.6.18 definitely has crippling bugs */ 25837e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko /* Vanilla and Fedora 2.6.29 seems to work */ 25847e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko p = utsname_buf.release; 25857e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko if (strtoul(p, &p, 10) < 2 || *p != '.') 25867e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko goto tracing; 25877e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko if (strtoul(++p, &p, 10) < 6 || *p != '.') 25887e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko goto tracing; 25897e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko if (strtoul(++p, &p, 10) < 29) 25907e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko goto tracing; 259196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko /* 259296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko * NB: even if this "succeeds", we can 259396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko * revert back to SIGTRAP if we later see 259496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko * that it didnt really work. 259596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko * Old kernels are known to lie here. 259696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko */ 259796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0, 259896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko (void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0) 259996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko ptrace_stop_sig = SIGTRAP | 0x80; 26001e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko } 26011e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif 260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2605f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS) 260696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) { 26071e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko /* 26081e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * We told ptrace to report SIGTRAP | 0x80 on this process 26091e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * but got bare SIGTRAP. This can be a genuine SIGTRAP: 26101e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * kill(pid, SIGTRAP), trap insn, etc; 26111e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * but be paranoid about it. 26121e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko */ 26131e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) { 26141d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko /* It's post-exec ptrace stop. Ignore it, 26151d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko * we will get syscall exit ptrace stop later. 26161d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko */ 26171d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko#ifdef TCB_WAITEXECVE 26181d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko tcp->flags &= ~TCB_WAITEXECVE; 26191d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko#endif 26201d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko goto tracing; 26211e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko } else { 26221e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko /* Take a better look... */ 26231e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko siginfo_t si; 26241d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko si.si_signo = 0; 26251e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si); 26261e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko /* 26271e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * Check some fields to make sure we see 26281e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * real SIGTRAP. 26291e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * Otherwise interpret it as ptrace stop. 26301e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * Real SIGTRAPs (int3 insn on x86, kill() etc) 26311e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * have these values: 26321e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * int3: kill -TRAP $pid: 26331e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP) 26341e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * si_errno:0 si_errno:(?) 26351e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * si_code:128 (SI_KERNEL) si_code:0 (SI_USER) 26361e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * si_pid:0 si_pid:(>0?) 26371e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * si_band:0 si_band:(?) 26381e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko * Ptrace stops have garbage there instead. 26391e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko */ 26401e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko if (si.si_signo != SIGTRAP 26411e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko || (si.si_code != SI_KERNEL && si.si_code != SI_USER) 26421e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko ) { 264396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code); 264496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko ptrace_stop_sig = SIGTRAP; 26451e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko } 26461e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko } 26471e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko } 26481e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif 26491e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko 265096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko if (WSTOPSIG(status) != ptrace_stop_sig) { 26511e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko /* This isn't a ptrace stop. */ 26521e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko 265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 2660732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 26681f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil unsigned long addr = 0; 26691f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil long pc = 0; 26709633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO) 26717b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# define PSR_RI 41 26727b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman struct siginfo si; 26731f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil long psr; 26747b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 2675932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IPSR, &psr); 2676932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IIP, &pc); 26777b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 26787b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 26797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman ptrace(PT_GETSIGINFO, pid, 0, (long) &si); 26807b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman addr = (unsigned long) si.si_addr; 26813a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO 26823a055d7d64222223da2550ca540043de7e3e232bRoland McGrath if (WSTOPSIG(status) == SIGSEGV || 26833a055d7d64222223da2550ca540043de7e3e232bRoland McGrath WSTOPSIG(status) == SIGBUS) { 26843a055d7d64222223da2550ca540043de7e3e232bRoland McGrath siginfo_t si; 26853a055d7d64222223da2550ca540043de7e3e232bRoland McGrath if (ptrace(PTRACE_GETSIGINFO, pid, 26863a055d7d64222223da2550ca540043de7e3e232bRoland McGrath 0, &si) == 0) 26873a055d7d64222223da2550ca540043de7e3e232bRoland McGrath addr = (unsigned long) 26883a055d7d64222223da2550ca540043de7e3e232bRoland McGrath si.si_addr; 26893a055d7d64222223da2550ca540043de7e3e232bRoland McGrath } 26907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 269176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 26927b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman tprintf("--- %s (%s) @ %lx (%lx) ---", 2693ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WSTOPSIG(status)), 26947b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman strsignal(WSTOPSIG(status)), pc, addr); 2695ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 26970569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (((tcp->flags & TCB_ATTACHED) || 26980569095472c93c8513edefcf31013503ce4c0589Roland McGrath tcp->nclone_threads > 0) && 269976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 2700e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2701e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, WSTOPSIG(status)); 2702e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 2704e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 270576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 270676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2707732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) { 270876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 270976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 271402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* we handled the STATUS, we are permitted to interrupt now. */ 271502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 271602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 2717732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) { 2718ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko /* ptrace() failed in trace_syscall() with ESRCH. 2719ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko * Likely a result of process disappearing mid-flight. 2720ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko * Observed case: exit_group() terminating 2721ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko * all processes in thread group. In this case, threads 2722ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko * "disappear" in an unpredictable moment without any 2723ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko * notification to strace via wait(). 2724ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko */ 2725ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (tcp->flags & TCB_ATTACHED) { 2726ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (tcp_last) { 2727ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko /* Do we have dangling line "syscall(param, param"? 2728ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko * Finish the line then. We cannot 2729ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko */ 2730ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko tcp_last->flags |= TCB_REPRINT; 2731ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko tprintf(" <unfinished ...>"); 2732ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 2733ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } 273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2735ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } else { 273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_KILL, 273776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, SIGTERM); 273876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 2743e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2744e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_GROUP_EXITING) { 2745e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (handle_group_exit(tcp, 0) < 0) 2746e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 2747e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath continue; 2748e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2749e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2752732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) { 275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 275976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 276176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 276276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 276376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 2764732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 276576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 276676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 276776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2768215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko } /* for each tcp */ 2769215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 2770215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko return 0; 2771215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko} 2772215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 2773215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic int 2774215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkotrace() 2775215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko{ 2776215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko int rc; 2777215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko struct tcb *tcbs; 2778215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 2779215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko while (nprocs != 0) { 2780215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko if (interrupted) 2781215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko return 0; 2782215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko if (interactive) 2783215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko sigprocmask(SIG_SETMASK, &empty_set, NULL); 2784215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko 2785215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko /* The loop of "wait for one tracee, serve it, repeat" 2786215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * may leave some tracees never served. 2787215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * Kernel provides no guarantees of fairness when you have 2788215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * many waitable tasks. 2789215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * Try strace -f with test/many_looping_threads.c example. 2790215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * To fix it, we collect *all* waitable tasks, then handle 2791215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko * them all, then repeat. 2792215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko */ 2793215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko tcbs = collect_stopped_tcbs(); 2794215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko if (!tcbs) 2795215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko break; 2796215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko rc = handle_stopped_tcbs(tcbs); 2797215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko if (rc) 2798215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko return rc; 279976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2803bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol; 280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b) 281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 281176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h> 281276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a) 281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 281876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist) 282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt; 282176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl 282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 282376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 282476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 282576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 282676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman VA_START(args, fmt); 2827b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (outf) { 2828b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath int n = vfprintf(outf, fmt, args); 2829b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (n < 0 && outf != stderr) 2830b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath perror(outfname == NULL 2831b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath ? "<writing to pipe>" : outfname); 2832b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath else 2833b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath curcol += n; 2834b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath } 283576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 283676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 283776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 283876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 283976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 28407e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenkoprintleader(struct tcb *tcp) 284176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 2842732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last) { 2843732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last->ptrace_errno) { 28447e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tcp_last->ptrace_errno = 0; 2845732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last->flags & TCB_INSYSCALL) { 28467e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tprintf(" <unavailable ...>\n"); 28477e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tcp_last->flags |= TCB_REPRINT; 28487e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko } else { 28497e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tprintf("= ? <unavailable>\n"); 2850732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2851732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else if (!outfname || followfork < 2 || tcp_last == tcp) { 2852732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko tprintf(" <unfinished ...>\n"); 28537e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tcp_last->flags |= TCB_REPRINT; 2854732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 285576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 285676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 285776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 285876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 285976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 286076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 286176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 286276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 286376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 286476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 286576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 286676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 286776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 286876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 286976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 287076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 287176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 287276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 287376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 287476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 287576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 287676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 287776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 287876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 287976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 288076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 288176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 288276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 288376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 288476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 288576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 288676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 288776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 288876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 288976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 289076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 289176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 289276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 289376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 289476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 289576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 289676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 289776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 289876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 289976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 290076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 2901ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void) 290276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 290376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 290476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 290576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 29069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2907ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 29089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2909ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint 2910ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size) 2911ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{ 29129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 29139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 2914553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 29159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 29169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 29179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 29189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 29199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 29209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 29219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 2922553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 2923ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko return writev(fd, iov, n); 29249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 29259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 29269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2927