strace.c revision 6b7a261ff81fdbe84769cb59852fa43cabc77e8f
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* 276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved. 776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without 976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions 1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met: 1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright 1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer. 1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright 1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer in the 1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * documentation and/or other materials provided with the distribution. 1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products 1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * derived from this software without specific prior written permission. 1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * $Id$ 3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h" 3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h> 3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h> 3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h> 3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h> 3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h> 4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h> 4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h> 4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h> 4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h> 4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h> 4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h> 4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h> 4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h> 4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 49134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX 50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h> 51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill 52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig)) 53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill 54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig)) 55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else 56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath /* kill() may choose arbitrarily the target task of the process group 57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath while we later wait on a that specific TID. PID process waits become 58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath TID task specific waits for a process under ptrace(2). */ 59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!" 60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# define my_tgkill(pid, tid, sig) kill ((tid), (sig)) 61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif 62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif 63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath 647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX) 657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h> 70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 74ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H 769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif 8096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ; 81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind; 82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg; 8396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko 8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8541c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0; 86b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaounsigned int ptrace_setoptions = 0; 87e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0; 88e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE; 89b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0; 90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/* 91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option. 92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice. 93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's, 94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process 95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild 96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID. 97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases 98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals, 99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between, 100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link. 101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0; 10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0; 10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0; 108a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0; 109eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 110b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL; 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 116b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL; 11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 118ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol; 119ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab; 120ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize; 12130145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinconst char *progname; 122eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ; 12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 124e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig); 125e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void); 126e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void); 127e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig); 12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 138e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd); 139e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig); 140e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void); 141ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv; 14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void); 146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd); 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 159ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 172b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwabusage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 173de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 174de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 175b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 176de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 178b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\ 17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 193ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\ 19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 197de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 199de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it 20017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath */ 202de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 215c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */ 216c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK 217c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0 218c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else 219c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1 220c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork() vfork() 221c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif 222c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger 22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd) 22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int flags, newflags; 22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((flags = fcntl(fd, F_GETFD, 0)) < 0) 22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_GETFD: %s\n", 23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newflags = flags | FD_CLOEXEC; 23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (flags == newflags) 23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fcntl(fd, F_SETFD, newflags) < 0) 24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_SETFD: %s\n", 24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids 25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations. 25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void 25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void) 25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4 25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int euid = geteuid(), uid = getuid(); 25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (euid != uid && setreuid(euid, uid) < 0) 26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: setreuid: %s\n", 26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin exit(1); 26410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 2684bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE 2694bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64 2704bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else 2714bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen 2724bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif 2734bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath 27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode) 27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 2804bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath if ((fp = fopen_for_output(path, mode)) == NULL) 28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: can't fopen '%s': %s\n", 28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, path, strerror(errno)); 28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fp && set_cloexec_flag(fileno(fp)) < 0) 28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fclose(fp); 28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fp = NULL; 28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fp; 29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1; 29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL 29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh" 29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish 30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3) 30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid. 30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command) 30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int fds[2]; 30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pipe(fds) < 0) 31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: pipe: %s\n", 31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(fds[1]) < 0) 31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((popen_pid = fork()) == -1) 32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fork: %s\n", 32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (popen_pid) 33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* parent */ 33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fdopen(fds[1], "w"); 34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } else 34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* child */ 34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fds[0] && (dup2(fds[0], 0) || close(fds[0]))) 34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: dup2: %s\n", 34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin execl(_PATH_BSHELL, "sh", "-c", command, NULL); 35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: execl: %s: %s\n", 35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, _PATH_BSHELL, strerror(errno)); 35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp) 36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (outfname && followfork > 1) { 3627a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char name[520 + sizeof(int) * 3]; 36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3657a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko sprintf(name, "%.512s.%u", outfname, tcp->pid); 36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((fp = strace_fopen(name, "w")) == NULL) 36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin tcp->outf = fp; 36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 37210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void) 37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tcbi; 37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Block user interruptions as we would leave the traced 38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * process stopped (process state T) if we would terminate in 38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * between PTRACE_ATTACH and wait4 () on SIGSTOP. 38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * We rely on cleanup () from this point on. 38402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 38502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 38602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 38702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid_t pid = fork(); 390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(1); 392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid) { /* parent */ 394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Wait for child to attach to straced process 396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * (our parent). Child SIGKILLs us after it attached. 397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Parent's wait() is unblocked by our death, 398ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * it proceeds to exec the straced program. 399ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 400ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pause(); 401ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(0); /* paranoia */ 402ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 403ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 404ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = tcbtab[tcbi]; 40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX 41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif 41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Reinitialize the output since it may have changed. */ 41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->outf = outf; 41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (newoutf(tcp) < 0) 41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (proc_open(tcp, 1) < 0) { 42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "trouble opening proc file\n"); 42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX 426ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (followfork && !daemonized_tracer) { 4277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; 42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath DIR *dir; 42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath dir = opendir(procdir); 43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (dir != NULL) { 43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath unsigned int ntid = 0, nerr = 0; 43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct dirent *de; 43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tid; 43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath while ((de = readdir(dir)) != NULL) { 4377a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (de->d_fileno == 0) 43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tid = atoi(de->d_name); 44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tid <= 0) 44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++ntid; 443aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) 44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++nerr; 445aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko else if (tid != tcbtab[tcbi]->pid) { 446418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(tid); 44721b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK; 44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nchildren++; 44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_threads++; 45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->parent = tcbtab[tcbi]; 45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 452aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (interactive) { 453aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko sigprocmask(SIG_SETMASK, &empty_set, NULL); 454aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (interrupted) 455aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko return; 456aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko sigprocmask(SIG_BLOCK, &blocked_set, NULL); 457aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko } 45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath closedir(dir); 4607a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ntid -= nerr; 4617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (ntid == 0) { 46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) { 4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko fprintf(stderr, ntid > 1 4687a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n" 4697a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n", 4707a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko tcbtab[tcbi]->pid, ntid); 47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 4737a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (opendir worked) */ 4747a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (-f) */ 47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif 47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* INTERRUPTED is going to be checked at the top of TRACE. */ 482ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 484ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It is our grandparent we trace, not a -p PID. 486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Don't want to just detach on exit, so... 487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags &= ~TCB_ATTACHED; 489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make parent go away. 491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Also makes grandparent's wait() unblock. 492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(getppid(), SIGKILL); 494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 495ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) 49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, 49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath "Process %u attached - interrupt to quit\n", 50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv) 50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct stat statbuf; 51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath const char *filename; 51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char pathname[MAXPATHLEN]; 51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int pid = 0; 51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath filename = argv[0]; 51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(filename, '/')) { 51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath errno = ENAMETOOLONG; 52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC 52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Debuggers customarily check the current directory 52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * first regardless of the path but doing that gives 52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * security geeks a panic attack. 53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (stat(filename, &statbuf) == 0) 53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */ 53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 53530145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin const char *path; 53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int m, n, len; 53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (path = getenv("PATH"); path && *path; path += m) { 53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(path, ':')) { 54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath n = strchr(path, ':') - path; 54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n + 1; 54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n = strlen(path); 54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (n == 0) { 54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!getcwd(pathname, MAXPATHLEN)) 54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = strlen(pathname); 54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (n > sizeof pathname - 1) 55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strncpy(pathname, path, n); 55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = n; 55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (len && pathname[len - 1] != '/') 55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pathname[len++] = '/'; 55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname + len, filename); 55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) == 0 && 56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Accept only regular files 56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath with some execute bits set. 56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath XXX not perfect, might still fail */ 56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath S_ISREG(statbuf.st_mode) && 56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (statbuf.st_mode & 0111)) 56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) < 0) { 56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "%s: %s: command not found\n", 57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath progname, filename); 57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 573a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin strace_child = pid = fork(); 574ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: fork"); 57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath cleanup(); 57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 578ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 579ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */ 580ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */ 581ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko ) { 582ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid = getpid(); 58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf != stderr) close (fileno (outf)); 58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS 58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Kludge for SGI, see proc_open for details. */ 58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_handler = foobar; 58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_flags = 0; 58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigemptyset(&sa.sa_mask); 59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigaction(SIGINT, &sa, NULL); 59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */ 59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD 59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pause(); 59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */ 595ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); /* stop HERE */ 59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */ 59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf!=stderr) 59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath close(fileno (outf)); 60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 601ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 602ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko perror("strace: ptrace(PTRACE_TRACEME, ...)"); 604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko exit(1); 605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (debug) 607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); 60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL || geteuid() == 0) { 61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath uid_t run_euid = run_uid; 61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath gid_t run_egid = run_gid; 61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISUID) 61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_euid = statbuf.st_uid; 61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISGID) 61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_egid = statbuf.st_gid; 61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * It is important to set groups before we 62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * lose privileges on setuid. 62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL) { 62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (initgroups(username, run_gid) < 0) { 62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("initgroups"); 62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setregid(run_gid, run_egid) < 0) { 62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setregid"); 63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setreuid(run_uid, run_euid) < 0) { 63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setreuid"); 63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath setreuid(run_uid, run_uid); 64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Induce an immediate stop so that the parent 644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will resume us with PTRACE_SYSCALL and display 645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * this execve call normally. 646c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * Unless of course we're on a no-MMU system where 647c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * we vfork()-ed, so we cannot stop the child. 648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 649c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger if (!strace_vforked) 650c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger kill(getpid(), SIGSTOP); 651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } else { 652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko struct sigaction sv_sigchld; 653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko sigaction(SIGCHLD, NULL, &sv_sigchld); 654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make sure it is not SIG_IGN, otherwise wait 656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will not block. 657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko signal(SIGCHLD, SIG_DFL); 659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Wait for grandchild to attach to us. 661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It kills child after that, and wait() unblocks. 662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko alarm(3); 664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko wait(NULL); 665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko alarm(0); 666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko sigaction(SIGCHLD, &sv_sigchld, NULL); 667ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath execv(pathname, argv); 67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath _exit(1); 67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* We are the tracer. */ 676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp = alloctcb(daemonized_tracer ? getppid() : pid); 677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* We want subsequent startup_attach() to attach to it. */ 679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags |= TCB_ATTACHED; 680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (proc_open(tcp, 0) < 0) { 683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko fprintf(stderr, "trouble opening proc file\n"); 684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko cleanup(); 685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko exit(1); 68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */ 68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 690b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX 691b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/* 692b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options. 693b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it, 694b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel. 695b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */ 696b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaostatic int 697b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaotest_ptrace_setoptions(void) 698b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{ 6992fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin int pid, expected_grandchild = 0, found_grandchild = 0; 7002fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin const unsigned int test_options = PTRACE_O_TRACECLONE | 7012fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin PTRACE_O_TRACEFORK | 7022fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin PTRACE_O_TRACEVFORK; 703b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 704b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao if ((pid = fork()) < 0) 705b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao return -1; 706b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao else if (pid == 0) { 707b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0) 708b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao _exit(1); 709b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao kill(getpid(), SIGSTOP); 710b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin _exit(fork() < 0); 711b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 712b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin 713b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin while (1) { 714b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin int status, tracee_pid; 715b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin 716b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin tracee_pid = wait(&status); 717b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (tracee_pid == -1) { 718b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (errno == EINTR) 719b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin continue; 720b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin else if (errno == ECHILD) 721b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao break; 722b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin perror("test_ptrace_setoptions"); 723b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin return -1; 724b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 725b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (tracee_pid != pid) { 7262fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin found_grandchild = tracee_pid; 727b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 && 728b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin errno != ESRCH) 729b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin kill(tracee_pid, SIGKILL); 730b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 731b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin else if (WIFSTOPPED(status)) { 7322fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin switch (WSTOPSIG(status)) { 7332fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin case SIGSTOP: 7342fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin if (ptrace(PTRACE_SETOPTIONS, pid, 7352fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin NULL, test_options) < 0) { 736b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao kill(pid, SIGKILL); 737b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin return -1; 738b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 7392fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin break; 7402fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin case SIGTRAP: 7412fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin if (status >> 16 == PTRACE_EVENT_FORK) { 7422fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin long msg = 0; 7432fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin 7442fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin if (ptrace(PTRACE_GETEVENTMSG, pid, 7452fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin NULL, (long) &msg) == 0) 7462fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin expected_grandchild = msg; 7472fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin } 7482fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin break; 749b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 750b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 && 751b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin errno != ESRCH) 752b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin kill(pid, SIGKILL); 753b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 754b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 7552fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin if (expected_grandchild && expected_grandchild == found_grandchild) 7562fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin ptrace_setoptions |= test_options; 757b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao return 0; 758b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao} 759b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif 760b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 76208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[]) 76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 76606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin int optF = 0; 76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[BUFSIZ]; 77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 77108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin progname = argv[0] ? argv[0] : "strace"; 77208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin 773ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 774ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 775418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) { 77608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 77708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 77808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 779418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) { 78008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 78108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 78208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 783ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp) 784ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]]; 785ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 788138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_sortby(DEFAULT_SORTBY); 789138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_personality(DEFAULT_PERSONALITY); 79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 795e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin "+cCdfFhiqrtTvVxz" 796ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 797ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "D" 798ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 799ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "a:e:o:O:p:s:S:u:E:")) != EOF) { 80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 802e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_BOTH) { 803e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin fprintf(stderr, "%s: -c and -C are mutually exclusive options\n", 804e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin progname); 805e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin exit(1); 806e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 807e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_ONLY_STATS; 808e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin break; 809e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin case 'C': 810e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_ONLY_STATS) { 811e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin fprintf(stderr, "%s: -c and -C are mutually exclusive options\n", 812e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin progname); 813e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin exit(1); 814e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 815e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_BOTH; 81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 820ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 821ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko case 'D': 822ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko daemonized_tracer = 1; 823ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko break; 824ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 82541c48227a86a176da333f713d5047240885f25ccRoland McGrath case 'F': 82606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin optF = 1; 82706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin break; 82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 8579c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 86017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 86117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 86217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 876de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if ((pid = atoi(optarg)) <= 0) { 87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 88254a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 885418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloc_tcb(pid, 0); 88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 891dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath if (max_strlen < 0) { 892dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath fprintf(stderr, 893dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath "%s: invalid -s argument: %s\n", 894dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath progname, optarg); 895dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath exit(1); 896dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath } 89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 904de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 905de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if (putenv(optarg) < 0) { 906de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 907de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath progname); 908de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath exit(1); 909de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath } 910de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 917d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath if ((optind == argc) == !pflag_seen) 918ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 919ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 920d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao if (pflag_seen && daemonized_tracer) { 921d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao fprintf(stderr, 922d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao "%s: -D and -p are mutually exclusive options\n", 923d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao progname); 924d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao exit(1); 925d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao } 926d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao 92706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin if (!followfork) 92806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin followfork = optF; 92906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin 930cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath if (followfork > 1 && cflag) { 931cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath fprintf(stderr, 932e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin "%s: (-c or -C) and -ff are mutually exclusive options\n", 933cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath progname); 934cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath exit(1); 935cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath } 936cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 94909553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath progname, username); 95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9608044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX 9618044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin if (followfork) { 9628044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin if (test_ptrace_setoptions() < 0) { 9638044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin fprintf(stderr, 9648044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin "Test for options supported by PTRACE_SETOPTIONS " 9658044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin "failed, giving up using this feature.\n"); 9668044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin ptrace_setoptions = 0; 9678044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin } 9688044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin if (debug) 9698044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin fprintf(stderr, "ptrace_setoptions = %#x\n", 9708044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin ptrace_setoptions); 9718044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin } 9728044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif 9738044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin 97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 97637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 97737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 97837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 97937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 98037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 98137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 98237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (followfork > 1) { 98337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath fprintf(stderr, "\ 98437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n", 98537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath progname); 98637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 98737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 98837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath 98910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((outf = strace_popen(outfname + 1)) == NULL) 99037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 99154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 99210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin else if (followfork <= 1 && 99310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin (outf = strace_fopen(outfname, "w")) == NULL) 99454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 99737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (!outfname || outfname[0] == '|' || outfname[0] == '!') 99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 99937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname && optind < argc) { 100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 1002369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 1003b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 100454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* Valid states here: 100554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath optind < argc pflag_seen outfname interactive 100654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 0 1 100754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 0 1 100854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 1 0 100954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 1 1 101054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath */ 101154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 101254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* STARTUP_CHILD must be called before the signal handlers get 101354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath installed below as they are inherited into the spawned process. 101454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath Also we do not need to be protected by them as during interruption 101554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath in the STARTUP_CHILD mode we kill the spawned process anyway. */ 101654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath if (!pflag_seen) 101754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath startup_child(&argv[optind]); 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 1043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 1046553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 1047553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath /* Make sure SIGCHLD has the default action so that waitpid 1048553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath definitely works without losing track of children. The user 1049553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath should not have given us a bogus state to inherit, but he might 1050553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath have. Arguably we should detect SIG_IGN here and pass it on 1051553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath to children, but probably noone really needs that. */ 1052553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sa.sa_handler = SIG_DFL; 1053553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sigaction(SIGCHLD, &sa, NULL); 1054bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1056ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pflag_seen || daemonized_tracer) 105702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_attach(); 105802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 1062a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin fflush(NULL); 1063a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (exit_code > 0xff) { 1064a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Child was killed by a signal, mimic that. */ 1065a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code &= 0xff; 1066a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin signal(exit_code, SIG_DFL); 1067a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin raise(exit_code); 1068a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Paranoia - what if this signal is not fatal? 1069a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin Exit with 128 + signo then. */ 1070a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code += 128; 1071a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin } 1072a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit(exit_code); 107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1075418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid 1076418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void) 10777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{ 10787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath /* Allocate some more TCBs and expand the table. 10797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath We don't want to relocate the TCBs because our 10807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath callers have pointers and it would be a pain. 10817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath So tcbtab is a table of pointers. Since we never 10827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free the TCBs, we allocate a single chunk of many. */ 10837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb **newtab = (struct tcb **) 10847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]); 10857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize, 10867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath sizeof *newtcbs); 10877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath int i; 10887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab == NULL || newtcbs == NULL) { 108976860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin fprintf(stderr, "%s: expand_tcbtab: out of memory\n", 109076860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin progname); 1091418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko cleanup(); 1092418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko exit(1); 10937b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath } 10947b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath for (i = tcbtabsize; i < 2 * tcbtabsize; ++i) 10957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath newtab[i] = &newtcbs[i - tcbtabsize]; 10967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtabsize *= 2; 10977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtab = newtab; 10987b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath} 10997b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 110110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed) 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1106418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if (nprocs == tcbtabsize) 1107418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko expand_tcbtab(); 1108418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko 1109ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1110ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 1113eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->parent = NULL; 1114eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nchildren = 0; 1115eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nzombies = 0; 1116eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD 111721b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao tcp->nclone_threads = 0; 1118eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->nclone_waiting = 0; 1119eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif 112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 1122ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = 0; 1123eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->stime.tv_sec = 0; 1124eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->stime.tv_usec = 0; 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 112710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (command_options_parsed) 112810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newoutf(tcp); 112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1132418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko fprintf(stderr, "%s: bug in alloc_tcb\n", progname); 1133418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko cleanup(); 1134418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko exit(1); 113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1137bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 1139418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching) 114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 1143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 114419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 114519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 1148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1153ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 11549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 11559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 11569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 11579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 11589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 116010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 11619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 11639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 11649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 11659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 11669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 116810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_stat) < 0) { 11699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 11719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 11729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 11739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 11749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 117610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_as) < 0) { 11779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 11799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 1181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 1183372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab tcp->pfd = open(proc, O_RDWR|O_EXCL); 1184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1185bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 1186372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab tcp->pfd = open(proc, O_RDWR); 1187bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 1188372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab if (tcp->pfd < 0) { 118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 119210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 11939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 11949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 11959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 1196bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1197bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 1198bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 1199bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 1200bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1201bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1202bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 1203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 1204bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 1205bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 1206bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1210bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 12189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 12229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 1223bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman break; 122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 122816a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1232553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 12369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 12429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 1247553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1256bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1257bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 1258bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 1259bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 12605ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko return -1; 1261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 12645ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko perror("PIOCSFL"); 12655ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko return -1; 1266bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1267bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 1269bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 127019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 127119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 127219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 127319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 127419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i); 127519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 127619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_execve); 127719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 127819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork); 127919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 128019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_forkall); 128119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 1282553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1 128319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork1); 128419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 128519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 128619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rfork1); 128719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 128819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 128919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rforkall); 129019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 129119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 129219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 129619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 129719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 130119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 130219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 130319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 130419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 130519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i); 130619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 13079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 131119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 131219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 131319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 131419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 131519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i); 131619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 13179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1321bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1322bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 1323bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg = S_SIG | S_SCE | S_SCX ; 1324bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 1325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 1326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1328bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 1337553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 13399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 13409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1344553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 1345bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 1346bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1347bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 1348bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1349553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 13529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 13569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 1357bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 1358bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 135976989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath if (known_scno(tcp) == SYS_execve) 136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 1363bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 13649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 13659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1366bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1367bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1368553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1372bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1373bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 1374bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 1375bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 1376bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 1377bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1378553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1383bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 1384553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (attaching < 2) { 13852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 13862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 13872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 13882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 13892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 13902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 13912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 1392553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 13932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 13942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 13952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 13962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 13972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 13982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 13992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 14002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 14012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 14022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 14032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 14042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 14052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 14062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 14072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 14082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 1409bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1426e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb * 142754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid) 142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 143054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 143154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (pid <= 0) 143254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return NULL; 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1434ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 143554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath struct tcb *tcp = tcbtab[i]; 143654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (tcp->pid == pid && (tcp->flags & TCB_INUSE)) 143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 143954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1443bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 144654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void) 144754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{ 144854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath int i; 144954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath struct tcb *tcp; 145054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath for (i = 0; i < tcbtabsize; i++) { 145154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath tcp = tcbtab[i]; 145254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (tcp->flags & TCB_INUSE) 145354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return tcp; 145454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath } 145554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return NULL; 145654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath} 145754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 145854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb * 145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1464ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = 0; i < tcbtabsize; i++) { 1465ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1474bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 1482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->nclone_threads > 0) { 1484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* There are other threads left in this process, but this 1485e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath is the one whose PID represents the whole process. 1486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath We need to keep this record around as a zombie until 1487e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath all the threads die. */ 1488e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_EXITING; 1489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return; 1490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1491e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 1494eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1495e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->parent != NULL) { 1496e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nchildren--; 1497e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD 1498e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1499e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_threads--; 1500e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif 150121b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao tcp->parent->nzombies++; 1502276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX 1503276ceb33f20fc41403e46684e441230296f6a433Roland McGrath /* Update `tcp->parent->parent->nchildren' and the other fields 1504276ceb33f20fc41403e46684e441230296f6a433Roland McGrath like NCLONE_DETACHED, only for zombie group leader that has 1505276ceb33f20fc41403e46684e441230296f6a433Roland McGrath already reported and been short-circuited at the top of this 1506276ceb33f20fc41403e46684e441230296f6a433Roland McGrath function. The same condition as at the top of DETACH. */ 1507276ceb33f20fc41403e46684e441230296f6a433Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1508276ceb33f20fc41403e46684e441230296f6a433Roland McGrath tcp->parent->nclone_threads == 0 && 1509276ceb33f20fc41403e46684e441230296f6a433Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1510276ceb33f20fc41403e46684e441230296f6a433Roland McGrath droptcb(tcp->parent); 1511276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif 1512e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent = NULL; 1513e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath } 1514e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath 1515e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->flags = 0; 151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 1519bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1520bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 1521bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 1522bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 1523bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1524bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 1525bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 1526bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1527bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1528553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */ 1529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 1530e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath rebuild_pollv(); /* Note, flags needs to be cleared by now. */ 153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1533eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1534822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman if (outfname && followfork > 1 && tcp->outf) 153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 1536eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1540bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 1554e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1555e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1556e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->parent->nclone_waiting--; 1557e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1559732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) 156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int 15681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp) 15691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{ 15701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int error = 0; 15711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int resumed = 0; 15721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 15731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* XXX This won't always be quite right (but it never was). 15741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath A waiter with argument 0 or < -1 is waiting for any pid in 15751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath a particular pgrp, which this child might or might not be 15761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath in. The waiter will only wake up if it's argument is -1 15771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath or if it's waiting for tcp->pid's pgrp. It makes a 15781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath difference to wake up a waiter when there might be more 15791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath traced children, because it could get a false ECHILD 15801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error. OTOH, if this was the last child in the pgrp, then 15811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath it ought to wake up and get ECHILD. We would have to 15821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath search the system for all pid's in the pgrp to be sure. 15831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 15841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && (t->waitpid == -1 || 15851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid)) 15861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath || (t->waitpid < 0 && t->waitpid == -getpid (t->pid))) 15871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath */ 15881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 15891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && 15901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->flags & TCB_SUSPENDED) && 15911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) { 15925ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko error = resume(tcp->parent); 15931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 15941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 15951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD 15961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && tcp->parent->nclone_waiting > 0) { 15971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Some other threads of our parent are waiting too. */ 15981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath unsigned int i; 15991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 16001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Resume all the threads that were waiting for this PID. */ 16011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 16021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 16031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 16041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 16051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 16061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid == tcp->pid) { 16071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 16081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 16091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 16101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 16111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (resumed == 0) 16121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Noone was waiting for this PID in particular, 16131bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath so now we might need to resume some wildcarders. */ 16141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 16151bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 16161bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 16171bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags 16181bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 16191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 16201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid <= 0 16211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ) { 16221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 16231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath break; 16241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 16251bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 16261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 16273bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif 16281bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 16291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath return error; 16301bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath} 16311bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 1632bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig 16350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath Never call DETACH twice on the same process as both unattached and 16360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath attached-unstopped processes give the same ESRCH. For unattached process we 16370a463880341945df08b6dc79134dc78cc38dc283Roland McGrath would SIGSTOP it and wait for its SIGSTOP notification forever. */ 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 1645ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX 16461bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int status, catch_sigstop; 1647a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath struct tcb *zombie = NULL; 1648a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1649a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* If the group leader is lingering only because of this other 1650a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath thread now dying, then detach the leader as well. */ 1651a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1652a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->parent->nclone_threads == 1 && 1653a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1654a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath zombie = tcp->parent; 1655ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 1658840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab clearbpt(tcp); 165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 16637bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * before detaching. Arghh. We go through hoops 16647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * to make a clean break of things. 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 16667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC) 16677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH 16687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH 16697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif 167002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 167102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the 167202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * expected SIGSTOP. We must catch exactly one as otherwise the 167302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * detached process would be left stopped (process state T). 167402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 167502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = (tcp->flags & TCB_STARTUP); 167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 16787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 16797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (errno != ESRCH) { 16807bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath /* Shouldn't happen. */ 16817bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: ptrace(PTRACE_DETACH, ...)"); 16827bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 1683134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid 1684134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath : tcp->pid), 1685134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath tcp->pid, 0) < 0) { 16867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 16877bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: checking sanity"); 16887bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 168902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD 169002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ? tcp->parent->pid : tcp->pid), 169102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid, SIGSTOP) < 0) { 16927bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 16937bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: stopping child"); 16947bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 169502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 169602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = 1; 1697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (catch_sigstop) { 169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 16997508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 17007508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 17017508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno == ECHILD) /* Already gone. */ 17027508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 17037508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != EINVAL) { 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 17057508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 17067508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 17077508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */ 17087508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* No __WALL here. */ 17097508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (waitpid(tcp->pid, &status, 0) < 0) { 17107508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) { 17117508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 17127508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 17137508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 17147508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE 17157508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* If no processes, try clones. */ 17167508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WCLONE, 17177508cb4678141d146d819120f6b5b428c103882eRoland McGrath NULL) < 0) { 17187508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) 17197508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 17207508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 17217508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 17227508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */ 17237508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 17247508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 17267508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif 172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 1732732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko ptrace_restart(PTRACE_DETACH, tcp, sig); 173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1735732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_CONT, tcp, 1736eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath WSTOPSIG(status) == SIGTRAP ? 0 1737732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko : WSTOPSIG(status)); 1738732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (error < 0) 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1741ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } 17427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */ 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 1749732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_DETACH, tcp, sig); 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1752bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 17531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume_from_tcp (tcp); 1754e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 1755e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 1760a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1761a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX 17620a463880341945df08b6dc79134dc78cc38dc283Roland McGrath if (zombie != NULL) { 17630a463880341945df08b6dc79134dc78cc38dc283Roland McGrath /* TCP no longer exists therefore you must not detach () it. */ 17640a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(zombie); 17650a463880341945df08b6dc79134dc78cc38dc283Roland McGrath } 1766a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif 1767a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1771bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1773e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig) 177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1782bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1790ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1791ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 1799ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko tprintf(" <unfinished ...>"); 1800ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18226d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST 182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 18256d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */ 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18448f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 18456d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[]; 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 18478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 18488f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[]; 18498f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif 185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1870bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1877ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv != NULL) 1878ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath free (pollv); 1879c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1880ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv == NULL) { 188146100d07257824da2ae1147da0324b5788c95501Roland McGrath fprintf(stderr, "%s: out of memory\n", progname); 1882ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath exit(1); 1883ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath } 1884ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 1885ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = j = 0; i < tcbtabsize; i++) { 1886ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 18909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 191110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(proc_poll_pipe[i]) < 0) { 191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1960bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 1966a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin _exit(1); 196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 1990a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin _exit(1); 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 2001bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 20025ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 20035ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else 20045ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 20055ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif 20069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 20229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 20399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 20629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 20749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 2075d870b3c31a0139b335a66a829169bacc74624c44John Hughes struct tcb *in_syscall = NULL; 20769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 20819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 209554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath tcp = first_used_tcb(); 209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 21089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 21099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 21109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 21119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 2112553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 21139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 21149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 21159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 21169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 21179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 21189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 21199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 21209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 21219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 21229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 21239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 21249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 21259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 21269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 21279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 21289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 21299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2153b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK 21549dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 2155b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif 215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 2158bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 21599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 2160bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 2161bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 2162bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 2163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 2164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 2165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_STATUS (tcp); 2166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 21675ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko ioctl_result = IOCTL_WSTOP (tcp); 2168553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2191bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2192bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 2193553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 22032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 22042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 22052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 22062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman IOCTL (tcp->pfd, PIOCRUN, 0); 22072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 22082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 2209553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2210553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 2216ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab curcol = tcp->curcol; 221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 2220bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2221bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 2222bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 2223bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 2224bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 2225bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 2226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 2227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 2228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 2229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 2230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 2231553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */ 223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 2234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 22389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 22399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 2240bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 22429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 22439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2250bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 22529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 22539dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 22549dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 2262e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 2263e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin && (qual_flags[what] & QUAL_SIGNAL)) { 226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 2266ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 2267ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 22685826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 22695826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 22705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 22715826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 22725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 2273ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 22745826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 22755826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 2279e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAGS_ONLY_STATS 2280e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin && (qual_flags[what] & QUAL_FAULT)) { 228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 2283ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2286bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2287bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 22885ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko continue; 2289553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 22919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2295ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab /* Remember current print column before continuing. */ 2296ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = curcol; 22979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 2298553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 2299372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) 2300553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 2301372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) 2302553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2303372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab { 230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2311bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2313e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the 2315e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related clone threads with it. This is called in three circumstances: 2316e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent). 2317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == 0 Continuing TCP will perform an exit_group syscall. 2318e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == other Continuing TCP with SIG will kill the process. 2319e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/ 2320e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int 2321e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig) 2322e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{ 2323e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* We need to locate our records of all the clone threads 2324e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related to TCP, either its children or siblings. */ 23257a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko struct tcb *leader = NULL; 23267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko 23277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (tcp->flags & TCB_CLONE_THREAD) 23287a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko leader = tcp->parent; 2329e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2330e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (sig < 0) { 23317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (leader != NULL && leader != tcp 23327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko && !(leader->flags & TCB_GROUP_EXITING) 23337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko && !(tcp->flags & TCB_STARTUP) 23347a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ) { 2335e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, 2336e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath "PANIC: handle_group_exit: %d leader %d\n", 2337e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->pid, leader ? leader->pid : -1); 23387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } 23397a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko /* TCP no longer exists therefore you must not detach() it. */ 23401bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS 23417a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko resume_from_tcp(tcp); 23421bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif 23430a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(tcp); /* Already died. */ 2344e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 2346a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* Mark that we are taking the process down. */ 2347a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING; 2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_ATTACHED) { 2349d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath detach(tcp, sig); 23505ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (leader != NULL && leader != tcp) 23511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2352732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else { 2353732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) { 2354732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko cleanup(); 2355732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko return -1; 2356732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2357732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (leader != NULL) { 23580569095472c93c8513edefcf31013503ce4c0589Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2359732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (leader != tcp) 2360732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko droptcb(tcp); 2361732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* The leader will report to us as parent now, 2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath and then we'll get to the SIG==-1 case. */ 2364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2365e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2369e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath} 2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2372ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX 2373ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaostatic int 2374ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaohandle_ptrace_event(int status, struct tcb *tcp) 2375ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao{ 2376ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (status >> 16 == PTRACE_EVENT_VFORK || 2377ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao status >> 16 == PTRACE_EVENT_CLONE || 2378ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao status >> 16 == PTRACE_EVENT_FORK) { 23792fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin long childpid; 2380ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao 2381ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) { 2382ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (errno != ESRCH) { 2383ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao fprintf(stderr, "\ 2384ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao%s: handle_ptrace_event: ptrace cannot get new child's pid\n", 2385ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao progname); 2386ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao cleanup(); 2387ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao exit(1); 2388ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao } 2389ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao return -1; 2390ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao } 2391ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao return handle_new_child(tcp, childpid, 0); 2392ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao } 2393ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao return 1; 2394ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao} 2395ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif 2396ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao 2397eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int 2398eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace() 239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 240576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 24062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 2407eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath static int wait4_options = __WALL; 24082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif 240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2411eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath while (nprocs != 0) { 2412222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko if (interrupted) 2413eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 2414eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 2415eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 241676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 24172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 2418eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL); 24195bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 24202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 24212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 24222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman errno = 0; 2423eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, wait4_options, 2424eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath cflag ? &ru : NULL); 24252f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 24265bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 24272f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 2428eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, __WCLONE, 2429eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath cflag ? &ru : NULL); 2430eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (pid == -1) { 2431eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath fprintf(stderr, "strace: clone wait4 " 24322f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman "failed: %s\n", strerror(errno)); 24332f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 24342f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 2435eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else 2436eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 2437eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */ 243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 243976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 244076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 244176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 244276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 2443eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 2444eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 2447eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath switch (wait_errno) { 2448eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case EINTR: 244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2450eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case ECHILD: 245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 2457eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 2458eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath default: 2459eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath errno = wait_errno; 2460eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath perror("strace: wait"); 2461eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return -1; 246276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 246376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 246410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pid == popen_pid) { 246510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (WIFEXITED(status) || WIFSIGNALED(status)) 246610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin popen_pid = -1; 246710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin continue; 246810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 2474e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX 247541c48227a86a176da333f713d5047240885f25ccRoland McGrath if (followfork) { 2476e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This is needed to go with the CLONE_PTRACE 2477e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath changes in process.c/util.c: we might see 2478e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath the child's initial trap before we see the 2479e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent return from the clone syscall. 2480e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath Leave the child suspended until the parent 2481e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath returns from its system call. Only then 2482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath will we have the association of parent and 2483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath child so that we know how to do clearbpt 2484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in the child. */ 2485418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(pid); 2486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED; 2487e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (!qflag) 2488e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "\ 2489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n", 2490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath pid); 24918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 2492e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else 2493e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This can happen if a clone call used 2494e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath CLONE_PTRACE itself. */ 2495eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif 2496e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath { 2497e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "unknown pid: %u\n", pid); 2498e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (WIFSTOPPED(status)) 2499e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2500e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath exit(1); 2501e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 250276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2503eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* set current output file */ 2504eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath outf = tcp->outf; 2505ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab curcol = tcp->curcol; 250684e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko if (cflag) { 2507eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX 250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 2510eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */ 251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2512eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 2513f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko if (tcp->flags & TCB_SUSPENDED) { 2514f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko /* 2515f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * Apparently, doing any ptrace() call on a stopped 2516f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * process, provokes the kernel to report the process 2517f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * status again on a subsequent wait(), even if the 2518f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * process has not been actually restarted. 2519f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * Since we have inspected the arguments of suspended 2520f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko * processes we end up here testing for this case. 2521f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko */ 2522f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko continue; 2523f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko } 252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 2525a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2526a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = 0x100 | WTERMSIG(status); 2527e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 25302efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath tprintf("+++ killed by %s %s+++", 25312efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 25322efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP 25332efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath WCOREDUMP(status) ? "(core dumped) " : 25342efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 25352efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath ""); 2536ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2538e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2539e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2540e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2542e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 2546a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2547a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = WEXITSTATUS(status); 254876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 25497a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status)); 25507a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED 25510569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING 25527a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING)) 25531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && !(tcp->flags & TCB_GROUP_EXITING) 25540569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif 25557a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ) { 255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 25577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko "PANIC: attached pid %u exited with %d\n", 25587a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko pid, WEXITSTATUS(status)); 25597a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } 25600a396906981a03f93c07cb912585d0679dd50899Roland McGrath if (tcp == tcp_last) { 25617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL) 25620a396906981a03f93c07cb912585d0679dd50899Roland McGrath tprintf(" <unfinished ... exit status %d>\n", 25630a396906981a03f93c07cb912585d0679dd50899Roland McGrath WEXITSTATUS(status)); 25640a396906981a03f93c07cb912585d0679dd50899Roland McGrath tcp_last = NULL; 25650a396906981a03f93c07cb912585d0679dd50899Roland McGrath } 2566e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2567e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2568e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2570e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 257876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 2580ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2582ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (ptrace_setoptions && (status >> 16)) { 2583ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (handle_ptrace_event(status, tcp) != 1) 2584ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao goto tracing; 2585ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao } 2586ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao 258702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 258802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Interestingly, the process may stop 258902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * with STOPSIG equal to some other signal 2590eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * than SIGSTOP if we happend to attach 259102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * just before the process takes a signal. 2592c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * A no-MMU vforked child won't send up a signal, 2593c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * so skip the first (lost) execve notification. 259402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 2595c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger if ((tcp->flags & TCB_STARTUP) && 2596c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger (WSTOPSIG(status) == SIGSTOP || strace_vforked)) { 259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 259976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 260302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_BPTSET) { 260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 260502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * One example is a breakpoint inherited from 260602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * parent through fork (). 260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 260876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 260976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2614ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX 2615ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (followfork && (tcp->parent == NULL) && ptrace_setoptions) 2616ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao if (ptrace(PTRACE_SETOPTIONS, tcp->pid, 2617ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao NULL, ptrace_setoptions) < 0 && 2618ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao errno != ESRCH) 2619ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao ptrace_setoptions = 0; 2620ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif 262176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 262276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 262376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2624eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (WSTOPSIG(status) != SIGTRAP) { 262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 2632732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 263376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 263676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2638e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 263976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 2640c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin siginfo_t si; 2641c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) 26426b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin long pc = 0; 26436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin long psr = 0; 26447b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 2645932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IPSR, &psr); 2646932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IIP, &pc); 26477b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 26486b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI 41 26497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 26506b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR " @ %lx" 26516b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG pc 26526b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else 26536b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR "%s" 26546b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG "" 26557b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 26576b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { 26586b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin tprintf("--- "); 26596b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin printsiginfo(&si, verbose(tcp)); 26606b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin tprintf(" (%s)" PC_FORMAT_STR " ---", 26616b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin strsignal(WSTOPSIG(status)), 26626b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin PC_FORMAT_ARG); 26636b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin } else 26646b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin tprintf("--- %s by %s" PC_FORMAT_STR " ---", 26656b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin strsignal(WSTOPSIG(status)), 26666b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin signame(WSTOPSIG(status)), 26676b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin PC_FORMAT_ARG); 2668ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 26700569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (((tcp->flags & TCB_ATTACHED) || 26710569095472c93c8513edefcf31013503ce4c0589Roland McGrath tcp->nclone_threads > 0) && 267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 2673e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2674e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, WSTOPSIG(status)); 2675e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 2677e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2680732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) { 268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 268702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* we handled the STATUS, we are permitted to interrupt now. */ 268802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 268902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 2690eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) { 2691eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* ptrace() failed in trace_syscall() with ESRCH. 2692eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Likely a result of process disappearing mid-flight. 2693eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Observed case: exit_group() terminating 2694eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * all processes in thread group. In this case, threads 2695eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * "disappear" in an unpredictable moment without any 2696eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * notification to strace via wait(). 2697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko */ 2698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (tcp->flags & TCB_ATTACHED) { 2699eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (tcp_last) { 2700eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* Do we have dangling line "syscall(param, param"? 2701eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Finish the line then. We cannot 2702eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath */ 2703eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp_last->flags |= TCB_REPRINT; 2704eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unfinished ...>"); 2705eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath printtrailer(); 2706eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath } 270776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2708ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } else { 2709eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath ptrace(PTRACE_KILL, 2710eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->pid, (char *) 1, SIGTERM); 271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 271476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 271576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 2716e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2717e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_GROUP_EXITING) { 2718e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (handle_group_exit(tcp, 0) < 0) 2719e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 2720e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath continue; 2721e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2722e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 272376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 272476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2725732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) { 272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 272776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 272876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 2737ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab /* Remember current print column before continuing. */ 2738ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = curcol; 2739732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2747bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2756e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab va_start(args, fmt); 2757b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (outf) { 2758b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath int n = vfprintf(outf, fmt, args); 2759ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab if (n < 0) { 2760ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab if (outf != stderr) 2761ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab perror(outfname == NULL 2762ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab ? "<writing to pipe>" : outfname); 2763ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab } else 2764b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath curcol += n; 2765b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath } 276676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 276776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 276876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 276976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 277076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 2771eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathprintleader(tcp) 2772eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstruct tcb *tcp; 277376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 2774732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last) { 2775eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (tcp_last->ptrace_errno) { 2776732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last->flags & TCB_INSYSCALL) { 2777eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unavailable>)"); 2778eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tabto(acolumn); 2779732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2780eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf("= ? <unavailable>\n"); 2781eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp_last->ptrace_errno = 0; 2782732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else if (!outfname || followfork < 2 || tcp_last == tcp) { 27837e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tcp_last->flags |= TCB_REPRINT; 2784eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unfinished ...>\n"); 2785732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 278676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 278776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 278876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 278976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 279076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 279176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 279276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 279376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 279476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 279576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 279676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 279776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 279876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 279976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 281176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 281276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 281876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 282176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 282376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 282476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 282576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 282676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 282776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 282876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 282976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 283076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 283176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 2832ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void) 283376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 283476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 283576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 283676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 28379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2838ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 28399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2840ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint 2841ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size) 2842ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{ 28439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 28449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 2845553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 28469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 28479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 28489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 28499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 28509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 28519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 28529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 2853553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 2854ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko return writev(fd, iov, n); 28559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 28569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 28579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2858