strace.c revision 08b623eb84266d4a2defc619fa78400c4e4f0dc1
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 8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 81b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint debug = 0, followfork = 0, followvfork = 0; 82b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0; 83b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0; 8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 8617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0; 8717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 88b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL; 8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 94b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL; 9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 96ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab; 97ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize; 9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname; 9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ; 10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1010a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig)); 10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void)); 10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void)); 10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig)); 10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */ 11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted; 11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */ 11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd)); 12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig)); 12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void)); 122ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv; 12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void)); 12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd)); 12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 140ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 154de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 155de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 156de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 157de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 176de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 177de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it 17917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 180de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath */ 181de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 19410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 19510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd) 19610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 19710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int flags, newflags; 19810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 19910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((flags = fcntl(fd, F_GETFD, 0)) < 0) 20010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 20110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_GETFD: %s\n", 20210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 20310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 20410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 20510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 20610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newflags = flags | FD_CLOEXEC; 20710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (flags == newflags) 20810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 20910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 21010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fcntl(fd, F_SETFD, newflags) < 0) 21110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 21210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fcntl F_SETFD: %s\n", 21310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 21410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 21510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 21610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 21710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 21810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids 22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations. 22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void 22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void) 22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4 22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int euid = geteuid(), uid = getuid(); 22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (euid != uid && setreuid(euid, uid) < 0) 23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: setreuid: %s\n", 23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin exit(1); 23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 2394bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE 2404bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64 2414bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else 2424bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen 2434bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif 2444bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath 24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode) 24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 2514bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath if ((fp = fopen_for_output(path, mode)) == NULL) 25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: can't fopen '%s': %s\n", 25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, path, strerror(errno)); 25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fp && set_cloexec_flag(fileno(fp)) < 0) 25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fclose(fp); 25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fp = NULL; 25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fp; 26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1; 26410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL 26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh" 26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 26810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 26910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish 27110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3) 27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid. 27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command) 27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int fds[2]; 27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pipe(fds) < 0) 28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: pipe: %s\n", 28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(fds[1]) < 0) 28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((popen_pid = fork()) == -1) 29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: fork: %s\n", 29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return NULL; 30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (popen_pid) 30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* parent */ 30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[0]); 31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fdopen(fds[1], "w"); 31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } else 31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* child */ 31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (fds[0] && (dup2(fds[0], 0) || close(fds[0]))) 31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin { 31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: dup2: %s\n", 31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, strerror(errno)); 32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin execl(_PATH_BSHELL, "sh", "-c", command, NULL); 32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: execl: %s: %s\n", 32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin progname, _PATH_BSHELL, strerror(errno)); 32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin _exit(1); 32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int 33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp) 33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (outfname && followfork > 1) { 33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin char name[MAXPATHLEN]; 33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin sprintf(name, "%s.%u", outfname, tcp->pid); 33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((fp = strace_fopen(name, "w")) == NULL) 33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return -1; 33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin tcp->outf = fp; 34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return 0; 34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 34402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 34502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void) 34602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 34702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tcbi; 34802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 34902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 35002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 35102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Block user interruptions as we would leave the traced 35202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * process stopped (process state T) if we would terminate in 35302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * between PTRACE_ATTACH and wait4 () on SIGSTOP. 35402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * We rely on cleanup () from this point on. 35502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 35602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 35702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 35802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 35902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 36002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = tcbtab[tcbi]; 36102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 36202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 36302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX 36402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 36502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 36602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif 36702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Reinitialize the output since it may have changed. */ 36802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->outf = outf; 36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (newoutf(tcp) < 0) 37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (proc_open(tcp, 1) < 0) { 37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "trouble opening proc file\n"); 37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX 38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (followfork) { 38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char procdir[MAXPATHLEN]; 38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath DIR *dir; 38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 38402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 38502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath dir = opendir(procdir); 38602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (dir != NULL) { 38702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath unsigned int ntid = 0, nerr = 0; 38802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct dirent *de; 38902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tid; 39002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath while ((de = readdir(dir)) != NULL) { 39102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (de->d_fileno == 0 || 39202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath de->d_name[0] == '.') 39302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 39402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tid = atoi(de->d_name); 39502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tid <= 0) 39602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 39702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++ntid; 39802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tid, 39902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (char *) 1, 0) < 0) 40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++nerr; 40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (tid != tcbtab[tcbi]->pid) { 40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (nprocs == tcbtabsize && 40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath expand_tcbtab()) 40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = NULL; 40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = alloctcb(tid); 40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp == NULL) 40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK; 41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nchildren++; 41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_threads++; 41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcbtab[tcbi]->nclone_detached++; 41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->parent = tcbtab[tcbi]; 41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) { 41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return; 41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath closedir(dir); 42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (nerr == ntid) { 42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) { 42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ntid -= nerr; 43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ntid > 1) 43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "\ 43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached with %u threads - interrupt to quit\n", 43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid, ntid); 43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "\ 43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached - interrupt to quit\n", 43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif 44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* INTERRUPTED is going to be checked at the top of TRACE. */ 44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) 45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, 45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath "Process %u attached - interrupt to quit\n", 45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv) 46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct stat statbuf; 46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath const char *filename; 46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char pathname[MAXPATHLEN]; 46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int pid = 0; 46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath filename = argv[0]; 47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(filename, '/')) { 47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath errno = ENAMETOOLONG; 47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC 47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Debuggers customarily check the current directory 48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * first regardless of the path but doing that gives 48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * security geeks a panic attack. 48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (stat(filename, &statbuf) == 0) 48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 48602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */ 48702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char *path; 48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int m, n, len; 49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (path = getenv("PATH"); path && *path; path += m) { 49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(path, ':')) { 49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath n = strchr(path, ':') - path; 49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n + 1; 49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n = strlen(path); 49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (n == 0) { 49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!getcwd(pathname, MAXPATHLEN)) 50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = strlen(pathname); 50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (n > sizeof pathname - 1) 50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strncpy(pathname, path, n); 50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = n; 50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (len && pathname[len - 1] != '/') 51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pathname[len++] = '/'; 51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname + len, filename); 51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) == 0 && 51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Accept only regular files 51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath with some execute bits set. 51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath XXX not perfect, might still fail */ 51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath S_ISREG(statbuf.st_mode) && 51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (statbuf.st_mode & 0111)) 51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) < 0) { 52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "%s: %s: command not found\n", 52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath progname, filename); 52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath switch (pid = fork()) { 52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath case -1: 52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: fork"); 52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath cleanup(); 53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath case 0: { 53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf != stderr) close (fileno (outf)); 53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS 53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Kludge for SGI, see proc_open for details. */ 53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_handler = foobar; 53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_flags = 0; 53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigemptyset(&sa.sa_mask); 54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigaction(SIGINT, &sa, NULL); 54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */ 54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD 54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pause(); 54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */ 54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath kill(getpid(), SIGSTOP); /* stop HERE */ 54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */ 54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (outf!=stderr) 54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath close(fileno (outf)); 55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: ptrace(PTRACE_TRACEME, ...)"); 55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (debug) 55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath kill(getpid(), SIGSTOP); 55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL || geteuid() == 0) { 55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath uid_t run_euid = run_uid; 56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath gid_t run_egid = run_gid; 56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISUID) 56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_euid = statbuf.st_uid; 56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISGID) 56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_egid = statbuf.st_gid; 56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * It is important to set groups before we 56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * lose privileges on setuid. 57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL) { 57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (initgroups(username, run_gid) < 0) { 57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("initgroups"); 57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setregid(run_gid, run_egid) < 0) { 57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setregid"); 57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setreuid(run_uid, run_euid) < 0) { 58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("setreuid"); 58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath setreuid(run_uid, run_uid); 58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Induce an immediate stop so that the parent 59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * will resume us with PTRACE_SYSCALL and display 59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * this execve call normally. 59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath kill(getpid(), SIGSTOP); 59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath execv(pathname, argv); 59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("strace: exec"); 59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath _exit(1); 60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath default: 60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if ((tcp = alloctcb(pid)) == NULL) { 60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath cleanup(); 60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (proc_open(tcp, 0) < 0) { 60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "trouble opening proc file\n"); 61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath cleanup(); 61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath exit(1); 61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_PROCFS */ 61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 61908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[]) 62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern int optind; 62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *optarg; 62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[BUFSIZ]; 62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 62908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin progname = argv[0] ? argv[0] : "strace"; 63008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin 631ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 632ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 63308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) { 63408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 63508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 63608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 63708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) { 63808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin fprintf(stderr, "%s: out of memory\n", progname); 63908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin exit(1); 64008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin } 641ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp) 642ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]]; 643ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 646138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_sortby(DEFAULT_SORTBY); 647138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_personality(DEFAULT_PERSONALITY); 64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 653de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) { 65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cflag++; 65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'F': 66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followvfork++; 66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 6949c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 69717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 69817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 69917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 713de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if ((pid = atoi(optarg)) <= 0) { 71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 71954a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 72210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((tcp = alloc_tcb(pid, 0)) == NULL) { 723de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 732dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath if (max_strlen < 0) { 733dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath fprintf(stderr, 734dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath "%s: invalid -s argument: %s\n", 735dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath progname, optarg); 736dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath exit(1); 737dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath } 73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 745de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 746de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if (putenv(optarg) < 0) { 747de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 748de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath progname); 749de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath exit(1); 750de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath } 751de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 758d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath if ((optind == argc) == !pflag_seen) 759ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 760ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 761cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath if (followfork > 1 && cflag) { 762cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath fprintf(stderr, 763cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath "%s: -c and -ff are mutually exclusive options\n", 764cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath progname); 765cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath exit(1); 766cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath } 767cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath 76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 78009553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath progname, username); 78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 79337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 79437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 79537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 79637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 79737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 79837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 79937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (followfork > 1) { 80037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath fprintf(stderr, "\ 80137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n", 80237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath progname); 80337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 80437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 80537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath 80610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if ((outf = strace_popen(outfname + 1)) == NULL) 80737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 80854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 80910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin else if (followfork <= 1 && 81010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin (outf = strace_fopen(outfname, "w")) == NULL) 81154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 81437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (!outfname || outfname[0] == '|' || outfname[0] == '!') 81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 81637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname && optind < argc) { 81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 819369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 845bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 848553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 849553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath /* Make sure SIGCHLD has the default action so that waitpid 850553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath definitely works without losing track of children. The user 851553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath should not have given us a bogus state to inherit, but he might 852553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath have. Arguably we should detect SIG_IGN here and pass it on 853553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath to children, but probably noone really needs that. */ 854553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sa.sa_handler = SIG_DFL; 855553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sigaction(SIGCHLD, &sa, NULL); 856bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 85802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (pflag_seen) 85902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_attach(); 86002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 86102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_child(&argv[optind]); 86202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8697b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathint 8707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathexpand_tcbtab() 8717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{ 8727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath /* Allocate some more TCBs and expand the table. 8737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath We don't want to relocate the TCBs because our 8747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath callers have pointers and it would be a pain. 8757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath So tcbtab is a table of pointers. Since we never 8767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free the TCBs, we allocate a single chunk of many. */ 8777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb **newtab = (struct tcb **) 8787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]); 8797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize, 8807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath sizeof *newtcbs); 8817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath int i; 8827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab == NULL || newtcbs == NULL) { 8837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab != NULL) 8847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free(newtab); 88576860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin fprintf(stderr, "%s: expand_tcbtab: out of memory\n", 88676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin progname); 8877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath return 1; 8887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath } 8897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath for (i = tcbtabsize; i < 2 * tcbtabsize; ++i) 8907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath newtab[i] = &newtcbs[i - tcbtabsize]; 8917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtabsize *= 2; 8927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtab = newtab; 8937b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 8947b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath return 0; 8957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath} 8967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 8977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 89910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed) 90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 904ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 905ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent = NULL; 90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->nchildren = 0; 9100962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath tcp->nzombies = 0; 911e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 912e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->nclone_threads = tcp->nclone_detached = 0; 913e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->nclone_waiting = 0; 914e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_sec = 0; 91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_usec = 0; 91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 92110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (command_options_parsed) 92210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newoutf(tcp); 92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 92610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname); 92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 930bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching) 93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching; 93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 938bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 93919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 94019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 943bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 948ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 9499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 9509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 9519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 9529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 9539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 95510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 9569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 9589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 9599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 9609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 9619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 96310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_stat) < 0) { 9649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 9669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 9679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 9689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 9699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 97110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd_as) < 0) { 9729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 9749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 976bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) { 979bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 980bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 981bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR)) < 0) { 982bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 98610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(tcp->pfd) < 0) { 9879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 9889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 9899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 990bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 991bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 992bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 993bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 994bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 995bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 996bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 997bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 998bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 999bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 1000bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1001bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1002bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1003bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1004bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 10129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 10169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 1017bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman break; 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1020bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 102216a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1026553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 10309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 10369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 1041553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1051bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 1052bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 1053bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 1054bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 1057bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 1058bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCSFL"); 1059bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1060bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1061bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 1063bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 106419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 106519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 106619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 106719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 106819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i); 106919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 107019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_execve); 107119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 107219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork); 107319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 107419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_forkall); 107519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 1076553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1 107719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork1); 107819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 107919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 108019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rfork1); 108119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 108219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 108319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rforkall); 108419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 108519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 108619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 109119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 109619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 109719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 109819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 109919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i); 110019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 11019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 110519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 110619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 110719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 110819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 110919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i); 111019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 11119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 1117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg = S_SIG | S_SCE | S_SCX ; 1118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 1119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 1120bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1122bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 1131553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT 113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 11339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 11349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1138553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 1139bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 1140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 1142bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1143553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 11469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 11509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 1151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 1152bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 115376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath if (known_scno(tcp) == SYS_execve) 115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 1157bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 11589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 11599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1160bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1161bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1162553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1167bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 1168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 1169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 1170bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 1171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1172553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1177bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 1178553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (attaching < 2) { 11792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 11802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 11812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 11822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 11832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 11842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 11852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 1186553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 11872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 11882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 11892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 11902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 11912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 11922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 11932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 11942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 11952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 11962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 11972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 11982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 11992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 12002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 12012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 12022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 1203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1204bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1218bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb * 122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid) 122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1227ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1228ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid && tcp->pid != pid) 123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1237bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1245ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = 0; i < tcbtabsize; i++) { 1246ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1255bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 1263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->nclone_threads > 0) { 1265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* There are other threads left in this process, but this 1266e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath is the one whose PID represents the whole process. 1267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath We need to keep this record around as a zombie until 1268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath all the threads die. */ 1269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_EXITING; 1270e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return; 1271e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 1275eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1276e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->parent != NULL) { 1277e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nchildren--; 1278e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD 1279e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_DETACHED) 1280e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_detached--; 1281e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1282e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_threads--; 1283e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif 12840962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED 12850962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath if (!(tcp->flags & TCB_CLONE_DETACHED)) 12860962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif 12870962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath tcp->parent->nzombies++; 1288e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent = NULL; 1289e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath } 1290e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath 1291e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->flags = 0; 129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 1295bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1296bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 1297bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 1298bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 1299bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1300bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 1301bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 1302bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1303bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1304553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */ 1305bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 1306e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath rebuild_pollv(); /* Note, flags needs to be cleared by now. */ 130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1309eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1310822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman if (outfname && followfork > 1 && tcp->outf) 131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 1312eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1316bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 1330e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1331e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1332e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->parent->nclone_waiting--; 1333e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) { 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("resume: ptrace(PTRACE_SYSCALL, ...)"); 133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13451bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int 13461bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp) 13471bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{ 13481bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int error = 0; 13491bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int resumed = 0; 13501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 13511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* XXX This won't always be quite right (but it never was). 13521bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath A waiter with argument 0 or < -1 is waiting for any pid in 13531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath a particular pgrp, which this child might or might not be 13541bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath in. The waiter will only wake up if it's argument is -1 13551bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath or if it's waiting for tcp->pid's pgrp. It makes a 13561bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath difference to wake up a waiter when there might be more 13571bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath traced children, because it could get a false ECHILD 13581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error. OTOH, if this was the last child in the pgrp, then 13591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath it ought to wake up and get ECHILD. We would have to 13601bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath search the system for all pid's in the pgrp to be sure. 13611bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 13621bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && (t->waitpid == -1 || 13631bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid)) 13641bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath || (t->waitpid < 0 && t->waitpid == -getpid (t->pid))) 13651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath */ 13661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 13671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && 13681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->flags & TCB_SUSPENDED) && 13691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) { 13701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error = resume(tcp->parent); 13711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 13721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 13731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD 13741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (tcp->parent && tcp->parent->nclone_waiting > 0) { 13751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Some other threads of our parent are waiting too. */ 13761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath unsigned int i; 13771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 13781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Resume all the threads that were waiting for this PID. */ 13791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 13801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 13811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 13821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 13831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 13841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid == tcp->pid) { 13851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 13861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ++resumed; 13871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 13881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 13891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (resumed == 0) 13901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath /* Noone was waiting for this PID in particular, 13911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath so now we might need to resume some wildcarders. */ 13921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath for (i = 0; i < tcbtabsize; i++) { 13931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath struct tcb *t = tcbtab[i]; 13941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (t->parent == tcp->parent && t != tcp 13951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && ((t->flags 13961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 13971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 13981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && t->waitpid <= 0 13991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath ) { 14001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume (t); 14011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath break; 14021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath } 14051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 14061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath return error; 14071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath} 14081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif 14091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 1410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14120a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig 14130a463880341945df08b6dc79134dc78cc38dc283Roland McGrath Never call DETACH twice on the same process as both unattached and 14140a463880341945df08b6dc79134dc78cc38dc283Roland McGrath attached-unstopped processes give the same ESRCH. For unattached process we 14150a463880341945df08b6dc79134dc78cc38dc283Roland McGrath would SIGSTOP it and wait for its SIGSTOP notification forever. */ 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 1423ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX 14241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int status, catch_sigstop; 1425a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath struct tcb *zombie = NULL; 1426a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1427a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* If the group leader is lingering only because of this other 1428a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath thread now dying, then detach the leader as well. */ 1429a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath if ((tcp->flags & TCB_CLONE_THREAD) && 1430a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->parent->nclone_threads == 1 && 1431a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath (tcp->parent->flags & TCB_EXITING)) 1432a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath zombie = tcp->parent; 1433ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif 143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = SIGKILL; 143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 14417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * before detaching. Arghh. We go through hoops 14427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * to make a clean break of things. 144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 14447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC) 14457bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH 14467bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH 14477bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif 144802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 144902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the 145002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * expected SIGSTOP. We must catch exactly one as otherwise the 145102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * detached process would be left stopped (process state T). 145202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 145302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = (tcp->flags & TCB_STARTUP); 145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 14567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 14577bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (errno != ESRCH) { 14587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath /* Shouldn't happen. */ 14597bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: ptrace(PTRACE_DETACH, ...)"); 14607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 1461134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid 1462134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath : tcp->pid), 1463134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath tcp->pid, 0) < 0) { 14647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 14657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: checking sanity"); 14667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 146702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD 146802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ? tcp->parent->pid : tcp->pid), 146902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid, SIGSTOP) < 0) { 14707bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 14717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: stopping child"); 14727bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 147302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 147402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = 1; 147502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (catch_sigstop) 147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 14777508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 14787508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 14797508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno == ECHILD) /* Already gone. */ 14807508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 14817508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != EINVAL) { 148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 14837508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 14847508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 14857508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */ 14867508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* No __WALL here. */ 14877508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (waitpid(tcp->pid, &status, 0) < 0) { 14887508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) { 14897508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 14907508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 14917508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 14927508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE 14937508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* If no processes, try clones. */ 14947508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WCLONE, 14957508cb4678141d146d819120f6b5b428c103882eRoland McGrath NULL) < 0) { 14967508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) 14977508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 14987508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 14997508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 15007508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */ 15017508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 15027508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 15047508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif 150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, 15117bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath tcp->pid, (char *) 1, sig)) < 0) { 151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* I died trying. */ 151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1, 15197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath WSTOPSIG(status) == SIGTRAP ? 15207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath 0 : WSTOPSIG(status))) < 0) { 152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_CONT, ...)"); 152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 15267bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */ 152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0) 153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1537bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 15381bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath error |= resume_from_tcp (tcp); 1539e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 1540e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 1545a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 1546a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX 15470a463880341945df08b6dc79134dc78cc38dc283Roland McGrath if (zombie != NULL) { 15480a463880341945df08b6dc79134dc78cc38dc283Roland McGrath /* TCP no longer exists therefore you must not detach () it. */ 15490a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(zombie); 15500a463880341945df08b6dc79134dc78cc38dc283Roland McGrath } 1551a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif 1552a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1556bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig) 156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(pid); 157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp) 157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1576bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1584ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1585ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16166d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST 161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 16196d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */ 162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16388f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 16396d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[]; 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 16418f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 16428f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[]; 16438f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif 164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1664bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1671ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv != NULL) 1672ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath free (pollv); 1673c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1674ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv == NULL) { 167546100d07257824da2ae1147da0324b5788c95501Roland McGrath fprintf(stderr, "%s: out of memory\n", progname); 1676ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath exit(1); 1677ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath } 1678ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 1679ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = j = 0; i < tcbtabsize; i++) { 1680ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 16849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 170510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (set_cloexec_flag(proc_poll_pipe[i]) < 0) { 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1753bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1754bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1755bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1795bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 1796bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 1797bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1798bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 1799bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 18009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 18169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 18339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 18569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 18689dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 1869d870b3c31a0139b335a66a829169bacc74624c44John Hughes struct tcb *in_syscall = NULL; 18709dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 18759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(0); 189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 19029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 19039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 19049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 19059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 1906553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 19079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 19089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 19099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 19109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 19119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 19129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 19139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 19149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 19159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 19169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 19179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 19189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 19199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 19209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 19219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 19229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 19239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1947b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK 19489dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 1949b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif 195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 1952bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 19539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 1954bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1955bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 1956bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 1957bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 1958bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_STATUS (tcp); 1960bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 1961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 1962553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 1985bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1986bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 1987553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 19972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 19982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 19992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 20002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman IOCTL (tcp->pfd, PIOCRUN, 0); 20012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 20022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 2003553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2004553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 2013bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2014bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 2015bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 2016bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 2017bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 2018bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 2019bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 2020bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 2021bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 2022bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 2023bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 2024553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */ 202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 2027bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 20319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 20329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 2033bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 20359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 20369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 20459dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 20469dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 20479dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) { 205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 2058ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 20605826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 20615826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 20625826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 20635826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 20645826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 20655826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printtrailer(tcp); 20665826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 20675826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_FAULT)) { 207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2077bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2078bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 2079bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman continue; 2080553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 20829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 20869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 2087553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 20889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 2089553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 2090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) { 2091553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2099bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2101e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2102e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the 2103e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related clone threads with it. This is called in three circumstances: 2104e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent). 2105e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == 0 Continuing TCP will perform an exit_group syscall. 2106e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == other Continuing TCP with SIG will kill the process. 2107e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/ 2108e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int 2109e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig) 2110e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{ 2111e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* We need to locate our records of all the clone threads 2112e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related to TCP, either its children or siblings. */ 2113e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD) 2114e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ? tcp->parent 2115e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath : tcp->nclone_detached > 0 2116e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ? tcp : NULL); 2117e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2118e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (sig < 0) { 21190569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (leader != NULL && leader != tcp && 21200569095472c93c8513edefcf31013503ce4c0589Roland McGrath !(leader->flags & TCB_GROUP_EXITING)) 2121e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, 2122e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath "PANIC: handle_group_exit: %d leader %d\n", 2123e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->pid, leader ? leader->pid : -1); 21240a463880341945df08b6dc79134dc78cc38dc283Roland McGrath /* TCP no longer exists therefore you must not detach () it. */ 21251bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS 21261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath resume_from_tcp (tcp); 21271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif 21280a463880341945df08b6dc79134dc78cc38dc283Roland McGrath droptcb(tcp); /* Already died. */ 2129e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2130e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 2131a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath /* Mark that we are taking the process down. */ 2132a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING; 2133e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_ATTACHED) { 2134d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath detach(tcp, sig); 21351bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath if (leader != NULL && leader != tcp) 21361bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2137e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2138e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) { 2139e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath perror("strace: ptrace(PTRACE_CONT, ...)"); 2140e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath cleanup(); 2141e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 2142e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2143e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 21440569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (leader != NULL) 21450569095472c93c8513edefcf31013503ce4c0589Roland McGrath leader->flags |= TCB_GROUP_EXITING; 2146e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (leader != NULL && leader != tcp) 2147e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath droptcb(tcp); 2148e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* The leader will report to us as parent now, 2149e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath and then we'll get to the SIG==-1 case. */ 2150e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2151e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2152e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2153e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 2154e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2155e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath} 2156e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 2157e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 21672f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 21682f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman static int wait4_options = __WALL; 21692f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif 217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while (nprocs != 0) { 217302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 217402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 21782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 21792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL); 21805bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 21812f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 21822f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 21832f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman errno = 0; 21842f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, wait4_options, 21852f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman cflag ? &ru : NULL); 21862f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 21875bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 21882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 21892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, __WCLONE, 21902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman cflag ? &ru : NULL); 21912f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman if (pid == -1) { 21922f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman fprintf(stderr, "strace: clone wait4 " 21932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman "failed: %s\n", strerror(errno)); 21942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 21952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 21962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else 219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 21982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */ 219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (wait_errno) { 220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ECHILD: 221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman errno = wait_errno; 222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: wait"); 222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 223110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pid == popen_pid) { 223210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (WIFEXITED(status) || WIFSIGNALED(status)) 223310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin popen_pid = -1; 223410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin continue; 223510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 2241e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX 2242e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (followfork || followvfork) { 2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This is needed to go with the CLONE_PTRACE 2244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath changes in process.c/util.c: we might see 2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath the child's initial trap before we see the 2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent return from the clone syscall. 2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath Leave the child suspended until the parent 2248e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath returns from its system call. Only then 2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath will we have the association of parent and 2250e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath child so that we know how to do clearbpt 2251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in the child. */ 225276860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin if (nprocs == tcbtabsize && 225376860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin expand_tcbtab()) 225476860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin tcp = NULL; 225576860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin else 225676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin tcp = alloctcb(pid); 225776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin if (tcp == NULL) { 2258e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath kill(pid, SIGKILL); /* XXX */ 2259e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2260e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED; 2262e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (!qflag) 2263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "\ 2264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n", 2265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath pid); 22668b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 2267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else 2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This can happen if a clone call used 2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath CLONE_PTRACE itself. */ 22708b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif 2271e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath { 2272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "unknown pid: %u\n", pid); 2273e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (WIFSTOPPED(status)) 2274e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2275e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath exit(1); 2276e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */ 228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Apparently, doing any ptrace() call on a stopped 229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process, provokes the kernel to report the process 229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * status again on a subsequent wait(), even if the 229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process has not been actually restarted. 229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Since we have inspected the arguments of suspended 229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * processes we end up here testing for this case. 229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 23022efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath tprintf("+++ killed by %s %s+++", 23032efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 23042efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP 23052efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath WCOREDUMP(status) ? "(core dumped) " : 23062efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 23072efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath ""); 230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2310e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2311e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2312e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u exited\n", pid); 23200569095472c93c8513edefcf31013503ce4c0589Roland McGrath if ((tcp->flags & TCB_ATTACHED) 23210569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING 23220569095472c93c8513edefcf31013503ce4c0589Roland McGrath && !(tcp->parent && (tcp->parent->flags & 23230569095472c93c8513edefcf31013503ce4c0589Roland McGrath TCB_GROUP_EXITING)) 23241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath && !(tcp->flags & TCB_GROUP_EXITING) 23250569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif 23260569095472c93c8513edefcf31013503ce4c0589Roland McGrath ) 232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "PANIC: attached pid %u exited\n", 232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 23300a396906981a03f93c07cb912585d0679dd50899Roland McGrath if (tcp == tcp_last) { 23310a396906981a03f93c07cb912585d0679dd50899Roland McGrath if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) 23320a396906981a03f93c07cb912585d0679dd50899Roland McGrath == TCB_INSYSCALL) 23330a396906981a03f93c07cb912585d0679dd50899Roland McGrath tprintf(" <unfinished ... exit status %d>\n", 23340a396906981a03f93c07cb912585d0679dd50899Roland McGrath WEXITSTATUS(status)); 23350a396906981a03f93c07cb912585d0679dd50899Roland McGrath tcp_last = NULL; 23360a396906981a03f93c07cb912585d0679dd50899Roland McGrath } 2337e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2338e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2339e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2341e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 2351ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 235302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 235402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Interestingly, the process may stop 235502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * with STOPSIG equal to some other signal 235602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * than SIGSTOP if we happend to attach 235702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * just before the process takes a signal. 235802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 235902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) { 236076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 236602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_BPTSET) { 236776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 236802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * One example is a breakpoint inherited from 236902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * parent through fork (). 237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 237476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) != SIGTRAP) { 238176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, 238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid, (char *) 1, 0) < 0) { 239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 23987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman unsigned long addr = 0, pc = 0; 23999633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO) 24007b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# define PSR_RI 41 24017b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman struct siginfo si; 24027b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman unsigned long psr; 24037b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 24047b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman upeek(pid, PT_CR_IPSR, &psr); 24057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman upeek(pid, PT_CR_IIP, &pc); 24067b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 24077b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 24087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman ptrace(PT_GETSIGINFO, pid, 0, (long) &si); 24097b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman addr = (unsigned long) si.si_addr; 24103a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO 24113a055d7d64222223da2550ca540043de7e3e232bRoland McGrath if (WSTOPSIG(status) == SIGSEGV || 24123a055d7d64222223da2550ca540043de7e3e232bRoland McGrath WSTOPSIG(status) == SIGBUS) { 24133a055d7d64222223da2550ca540043de7e3e232bRoland McGrath siginfo_t si; 24143a055d7d64222223da2550ca540043de7e3e232bRoland McGrath if (ptrace(PTRACE_GETSIGINFO, pid, 24153a055d7d64222223da2550ca540043de7e3e232bRoland McGrath 0, &si) == 0) 24163a055d7d64222223da2550ca540043de7e3e232bRoland McGrath addr = (unsigned long) 24173a055d7d64222223da2550ca540043de7e3e232bRoland McGrath si.si_addr; 24183a055d7d64222223da2550ca540043de7e3e232bRoland McGrath } 24197b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 242076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 24217b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman tprintf("--- %s (%s) @ %lx (%lx) ---", 2422ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WSTOPSIG(status)), 24237b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman strsignal(WSTOPSIG(status)), pc, addr); 242476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 242576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 24260569095472c93c8513edefcf31013503ce4c0589Roland McGrath if (((tcp->flags & TCB_ATTACHED) || 24270569095472c93c8513edefcf31013503ce4c0589Roland McGrath tcp->nclone_threads > 0) && 242876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 2429e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2430e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, WSTOPSIG(status)); 2431e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 243276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 2433e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 243576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 243676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 243776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman WSTOPSIG(status)) < 0) { 243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 243976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 244076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 244176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 244276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 244376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 244476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 244502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* we handled the STATUS, we are permitted to interrupt now. */ 244602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 244702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_KILL, 245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, SIGTERM); 245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 245776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 245876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 2459e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2460e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_GROUP_EXITING) { 2461e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (handle_group_exit(tcp, 0) < 0) 2462e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 2463e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath continue; 2464e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2465e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) { 246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_CONT, ...)"); 247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) { 248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2490bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 249176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol; 249376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 249476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b) 249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 249876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h> 249976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a) 250076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 250276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 250376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 250476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist) 250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt; 250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl 250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 251276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman VA_START(args, fmt); 2514b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (outf) { 2515b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath int n = vfprintf(outf, fmt, args); 2516b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (n < 0 && outf != stderr) 2517b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath perror(outfname == NULL 2518b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath ? "<writing to pipe>" : outfname); 2519b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath else 2520b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath curcol += n; 2521b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath } 252276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 252376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 252576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 252676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 252776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp) 252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) { 253176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last->flags |= TCB_REPRINT; 253276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 253376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 253476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 253576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 253876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 253976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 254876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 255076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 255376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 255576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 255776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 255876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 255976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 256076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 256176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 256276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 256376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 256476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 256576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 256676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 256776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 257076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 257876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp) 258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 258276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 25859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2586ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 25879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 25889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) { 25899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 25909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 25919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 2592553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 25939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 25949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 25959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 25969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 25979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 25989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 25999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 2600553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 26019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return writev (fd, iov, n); 26029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 26039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 26049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2605