strace.c revision 7b54a7ae61d0eda798575f77d898a24dda7a0952
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 332ee6e45f36566e8735b35ffad40bfcc626a25a98Wichert Akkerman#include <sys/types.h> 3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h" 3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 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 497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX) 507b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 517b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 527b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 53bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 54bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h> 55bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 56bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 5776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 5876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 59ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 601d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H 619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 6376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 641d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif 6576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint debug = 0, followfork = 0, followvfork = 0, interactive = 0; 6776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint rflag = 0, tflag = 0, dtime = 0, cflag = 0; 6876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint iflag = 0, xflag = 0, qflag = 0; 6976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pflag_seen = 0; 7076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 7117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 7217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0; 7317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *username = NULL; 7576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 7676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *outfname = NULL; 8176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 82ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab; 83ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize; 8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname; 8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ; 8676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void)); 8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void)); 8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig)); 9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */ 9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted; 9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */ 10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 102bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd)); 10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig)); 10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void)); 107ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv; 10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void)); 11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd)); 11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 125ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 130bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 139de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 140de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 141de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 142de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 161de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 162de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 163de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it 16417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 165de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath */ 166de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanmain(argc, argv) 18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint argc; 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *argv[]; 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern int optind; 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *optarg; 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[BUFSIZ]; 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 193ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 194ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]); 195ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]); 196ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp) 197ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]]; 198ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname = argv[0]; 20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(DEFAULT_SORTBY); 20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_personality(DEFAULT_PERSONALITY); 20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) { 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cflag++; 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'F': 22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followvfork++; 22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 23576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 24576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 24776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 24876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 2509c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 25176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 25276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 25317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 25417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 25517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 25676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 25776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 25876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 25976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 26076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 26176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 26376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 26476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 26676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 269de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if ((pid = atoi(optarg)) <= 0) { 27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 27554a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = alloctcb(pid)) == NULL) { 279de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 295de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 296de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if (putenv(optarg) < 0) { 297de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath fprintf(stderr, "%s: out of memory\n", 298de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath progname); 299de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath exit(1); 300de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath } 301de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 308ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath if (optind == argc && !pflag_seen) 309ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 310ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 34054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman long f; 34154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman 34237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 34337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 34437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 34537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 34637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 34737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 34837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (followfork > 1) { 34937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath fprintf(stderr, "\ 35037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n", 35137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath progname); 35237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 35337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 35437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath 35537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if ((outf = popen(outfname + 1, "w")) == NULL) { 35637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath fprintf(stderr, "%s: can't popen '%s': %s\n", 35737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath progname, outfname + 1, 35837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath strerror(errno)); 35937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath exit(1); 36037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 36137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath } 36237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath else if ((outf = fopen(outfname, "w")) == NULL) { 36376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: can't fopen '%s': %s\n", 36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, outfname, strerror(errno)); 36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 36754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman 36854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) { 36954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman perror("failed to get flags for outputfile"); 37054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 37154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 37254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman 37354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) { 37454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman perror("failed to set flags for outputfile"); 37554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 37654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 38337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (!outfname || outfname[0] == '|' || outfname[0] == '!') 38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 38537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname && optind < argc) { 38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 388369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 390ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (c = 0; c < tcbtabsize; c++) { 391ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[c]; 39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Reinitialize the output since it may have changed. */ 39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; 39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 396bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_open(tcp, 1) < 0) { 39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "trouble opening proc file\n"); 39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 40370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath# ifdef LINUX 40470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (tcp->flags & TCB_CLONE_THREAD) 40570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath continue; 4067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (followfork) { 40770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath char procdir[MAXPATHLEN]; 40870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath DIR *dir; 40970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 41070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath dir = opendir(procdir); 41170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (dir != NULL) { 41270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath unsigned int ntid = 0, nerr = 0; 41370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath struct dirent *de; 41470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath int tid; 41570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath while ((de = readdir(dir)) != NULL) { 41670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (de->d_fileno == 0 || 41770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath de->d_name[0] == '.') 41870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath continue; 41970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tid = atoi(de->d_name); 42070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (tid <= 0) 42170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath continue; 42270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath ++ntid; 42370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (ptrace(PTRACE_ATTACH, tid, 42470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath (char *) 1, 0) < 0) 42570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath ++nerr; 42670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath else if (tid != tcbtab[c]->pid) { 4277b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (nprocs == tcbtabsize && 4287b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath expand_tcbtab()) 4297b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcp = NULL; 4307b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath else 4317b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcp = alloctcb(tid); 43270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (tcp == NULL) { 43370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath fprintf(stderr, "%s: out of memory\n", 43470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath progname); 43570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath exit(1); 43670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 4377b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK; 43870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tcbtab[c]->nchildren++; 43970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tcbtab[c]->nclone_threads++; 44070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tcbtab[c]->nclone_detached++; 44170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tcp->parent = tcbtab[c]; 44270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 44370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 44470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath closedir(dir); 44570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (nerr == ntid) { 44670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 44770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath droptcb(tcp); 44870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath continue; 44970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 45070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (!qflag) { 45170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath ntid -= nerr; 45270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath if (ntid > 1) 45370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath fprintf(stderr, "\ 45470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrathProcess %u attached with %u threads - interrupt to quit\n", 45570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tcp->pid, ntid); 45670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath else 45770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath fprintf(stderr, "\ 45870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrathProcess %u attached - interrupt to quit\n", 45970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath tcp->pid); 46070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 46170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath continue; 46270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 46370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath } 46470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath# endif 46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("attach: ptrace(PTRACE_ATTACH, ...)"); 46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 46976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 470bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "Process %u attached - interrupt to quit\n", 474c3266d51f0b4c0af082000a02649e37f992dbc8bRoland McGrath tcp->pid); 47576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 47676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 477ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath if (!pflag_seen) { 47876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct stat statbuf; 47976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char *filename; 48076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char pathname[MAXPATHLEN]; 48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman filename = argv[optind]; 483bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath if (strchr(filename, '/')) { 484bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 485bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath errno = ENAMETOOLONG; 486bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath perror("strace: exec"); 487bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath exit(1); 488bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath } 48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname, filename); 490bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath } 49176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC 49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Debuggers customarily check the current directory 49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * first regardless of the path but doing that gives 49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * security geeks a panic attack. 49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (stat(filename, &statbuf) == 0) 49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname, filename); 49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */ 50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 50176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char *path; 50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int m, n, len; 50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (path = getenv("PATH"); path && *path; path += m) { 50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (strchr(path, ':')) { 50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = strchr(path, ':') - path; 50776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman m = n + 1; 50876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 51076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman m = n = strlen(path); 51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n == 0) { 51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman getcwd(pathname, MAXPATHLEN); 51376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman len = strlen(pathname); 51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 515bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath else if (n > sizeof pathname - 1) 516bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath continue; 51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 51876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strncpy(pathname, path, n); 51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman len = n; 52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (len && pathname[len - 1] != '/') 52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pathname[len++] = '/'; 52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname + len, filename); 524ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath if (stat(pathname, &statbuf) == 0 && 525ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath /* Accept only regular files 526ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath with some execute bits set. 527ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath XXX not perfect, might still fail */ 528ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath S_ISREG(statbuf.st_mode) && 529ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath (statbuf.st_mode & 0111)) 53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (stat(pathname, &statbuf) < 0) { 53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: %s: command not found\n", 53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, filename); 53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (pid = fork()) { 53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: fork"); 54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: { 545bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 546bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (outf != stderr) close (fileno (outf)); 54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Kludge for SGI, see proc_open for details. */ 54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = foobar; 55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 554bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pause(); 556bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 557bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(getpid(), SIGSTOP); /* stop HERE */ 558553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 559bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 560553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (outf!=stderr) 5617987cdf192632516d6ba493b0a9943f5a3a7c362Wichert Akkerman close(fileno (outf)); 562bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman 56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_TRACEME, ...)"); 56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(getpid(), SIGSTOP); 56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL || geteuid() == 0) { 57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman uid_t run_euid = run_uid; 57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gid_t run_egid = run_gid; 57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (statbuf.st_mode & S_ISUID) 57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_euid = statbuf.st_uid; 57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (statbuf.st_mode & S_ISGID) 57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_egid = statbuf.st_gid; 57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 58076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * It is important to set groups before we 58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * lose privileges on setuid. 58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 5835ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (username != NULL) { 5845ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (initgroups(username, run_gid) < 0) { 5855ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("initgroups"); 5865ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 5875ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 5885ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (setregid(run_gid, run_egid) < 0) { 5895ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("setregid"); 5905ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 5915ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 5925ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (setreuid(run_uid, run_euid) < 0) { 5935ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("setreuid"); 5945ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 5955ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(run_uid, run_uid); 600bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 60176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman execv(pathname, &argv[optind]); 60376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: exec"); 60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(1); 60576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = alloctcb(pid)) == NULL) { 60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "tcb table full\n"); 61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 61176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 613bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_open(tcp, 0) < 0) { 61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "trouble opening proc file\n"); 61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 619bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 620bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fake_execve(tcp, pathname, &argv[optind], environ); 622bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 63276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 651bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 654553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 655553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath /* Make sure SIGCHLD has the default action so that waitpid 656553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath definitely works without losing track of children. The user 657553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath should not have given us a bogus state to inherit, but he might 658553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath have. Arguably we should detect SIG_IGN here and pass it on 659553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath to children, but probably noone really needs that. */ 660553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sa.sa_handler = SIG_DFL; 661553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sigaction(SIGCHLD, &sa, NULL); 662bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp) 67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char name[MAXPATHLEN]; 67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman FILE *fp; 67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname && followfork > 1) { 67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(name, "%s.%u", outfname, tcp->pid); 67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fp = fopen(name, "w"); 68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (fp == NULL) { 68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fopen"); 68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = fp; 69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 6957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathint 6967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathexpand_tcbtab() 6977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{ 6987b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath /* Allocate some more TCBs and expand the table. 6997b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath We don't want to relocate the TCBs because our 7007b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath callers have pointers and it would be a pain. 7017b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath So tcbtab is a table of pointers. Since we never 7027b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free the TCBs, we allocate a single chunk of many. */ 7037b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb **newtab = (struct tcb **) 7047b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]); 7057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize, 7067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath sizeof *newtcbs); 7077b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath int i; 7087b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab == NULL || newtcbs == NULL) { 7097b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath if (newtab != NULL) 7107b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free(newtab); 7117b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath return 1; 7127b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath } 7137b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath for (i = tcbtabsize; i < 2 * tcbtabsize; ++i) 7147b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath newtab[i] = &newtcbs[i - tcbtabsize]; 7157b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtabsize *= 2; 7167b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtab = newtab; 7177b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 7187b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath return 0; 7197b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath} 7207b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 7217b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid) 72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 729ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 730ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent = NULL; 73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->nchildren = 0; 7350962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath tcp->nzombies = 0; 736e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 737e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->nclone_threads = tcp->nclone_detached = 0; 738e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->nclone_waiting = 0; 739e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_sec = 0; 74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_usec = 0; 74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 752bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching) 75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching; 75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 760bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 76119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 76219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 765bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 770ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 7719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 7729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 7739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 7749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 7759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 7769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 7779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) { 7789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 7799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 7809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 7819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) { 7829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 7839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 7849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 7859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 7869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 7879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 7889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 7899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 7909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) { 7919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 7929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 7939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 7949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) { 7959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 7969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 7979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 7989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 7999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 8009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 8019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 8029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 8039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) { 8049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 8059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 8069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 8079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) { 8089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 8099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 8109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 8119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 813bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) { 816bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 817bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 818bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR)) < 0) { 819bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 8239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) { 8249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 8259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 8269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 8279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) { 8289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 8299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 8309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 8319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 832bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 834bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 835bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 836bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 837bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 838bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 839bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 840bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 842bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 844bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 845bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 846bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 8549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 8589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 859bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman break; 86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 862bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 86416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 868553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 8729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 8789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 883553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 892bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 893bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 894bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 895bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 896bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 897bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 898bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 899bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 900bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCSFL"); 901bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 902bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 903bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 905bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 90619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 90719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 90819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 90919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 91019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i); 91119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 91219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_execve); 91319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 91419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork); 91519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 91619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_forkall); 91719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 918553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1 91919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork1); 92019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 92119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 92219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rfork1); 92319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 92419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 92519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rforkall); 92619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 92719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 92819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 93219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 93319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 93719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 93819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 93919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 94019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 94119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i); 94219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 9439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 94719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 94819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 94919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 95019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 95119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i); 95219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 9539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 957bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 958bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg = S_SIG | S_SCE | S_SCX ; 960bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 962bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 963bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 964bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 973553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT 97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 9759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 9769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 980553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 981bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 982bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 983bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 984bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 985553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 9889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 9929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 993bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 994bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 995bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->scno == SYS_execve) 99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 999bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 10009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 10019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1002bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1003bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1004553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1008bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1009bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 1010bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 1011bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 1012bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 1013bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1014553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1016bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1018bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1019bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 1020553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (attaching < 2) { 10212e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 10222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 10232e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 10242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 10252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 10262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 10272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 1028553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 10292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 10302e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 10312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 10322e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 10332e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 10342e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 10352e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 10362e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 10372e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 10382e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 10392e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 10402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 10412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 10422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 10432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 10442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 1045bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1046bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1060bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1062e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb * 106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid) 106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1069ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1070ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid && tcp->pid != pid) 107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1079bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1087ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = 0; i < tcbtabsize; i++) { 1088ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1097bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 1105e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1106e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->nclone_threads > 0) { 1107e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* There are other threads left in this process, but this 1108e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath is the one whose PID represents the whole process. 1109e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath We need to keep this record around as a zombie until 1110e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath all the threads die. */ 1111e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_EXITING; 1112e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return; 1113e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1114e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 1117eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1118e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->parent != NULL) { 1119e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nchildren--; 1120e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD 1121e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_DETACHED) 1122e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_detached--; 1123e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1124e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent->nclone_threads--; 1125e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif 11260962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED 11270962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath if (!(tcp->flags & TCB_CLONE_DETACHED)) 11280962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif 11290962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath tcp->parent->nzombies++; 1130e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->parent = NULL; 1131e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath } 1132e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath 1133e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath tcp->flags = 0; 113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 1137bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 1139bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 1140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 1141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1142bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 1143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 1144bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1146553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */ 1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 1148e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath rebuild_pollv(); /* Note, flags needs to be cleared by now. */ 114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1151eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1152822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman if (outfname && followfork > 1 && tcp->outf) 115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 1154eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1158bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 1172e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1173e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_CLONE_THREAD) 1174e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->parent->nclone_waiting--; 1175e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) { 117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("resume: ptrace(PTRACE_SYSCALL, ...)"); 117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1187bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */ 119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 1197ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX 1198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath int status, resumed; 1199ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif 120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = SIGKILL; 120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 12077bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * before detaching. Arghh. We go through hoops 12087bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * to make a clean break of things. 120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 12107bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC) 12117bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH 12127bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH 12137bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif 121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 12167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 12177bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (errno != ESRCH) { 12187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath /* Shouldn't happen. */ 12197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: ptrace(PTRACE_DETACH, ...)"); 12207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 12217bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (kill(tcp->pid, 0) < 0) { 12227bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 12237bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: checking sanity"); 12247bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 12257bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (kill(tcp->pid, SIGSTOP) < 0) { 12267bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 12277bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: stopping child"); 12287bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 12297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else { 123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 12317508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 12327508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 12337508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno == ECHILD) /* Already gone. */ 12347508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 12357508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != EINVAL) { 123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 12377508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 12387508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 12397508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */ 12407508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* No __WALL here. */ 12417508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (waitpid(tcp->pid, &status, 0) < 0) { 12427508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) { 12437508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 12447508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 12457508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 12467508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE 12477508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* If no processes, try clones. */ 12487508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WCLONE, 12497508cb4678141d146d819120f6b5b428c103882eRoland McGrath NULL) < 0) { 12507508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) 12517508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 12527508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 12537508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 12547508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */ 12557508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 12567508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 12587508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif 125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, 12657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath tcp->pid, (char *) 1, sig)) < 0) { 126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* I died trying. */ 126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1, 12737bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath WSTOPSIG(status) == SIGTRAP ? 12747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath 0 : WSTOPSIG(status))) < 0) { 127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_CONT, ...)"); 127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 12817bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */ 128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0) 128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1292bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 1293e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath resumed = 0; 1294e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1295e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* XXX This won't always be quite right (but it never was). 1296e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath A waiter with argument 0 or < -1 is waiting for any pid in 1297e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath a particular pgrp, which this child might or might not be 1298e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in. The waiter will only wake up if it's argument is -1 1299e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath or if it's waiting for tcp->pid's pgrp. It makes a 1300e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath difference to wake up a waiter when there might be more 1301e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath traced children, because it could get a false ECHILD 1302e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath error. OTOH, if this was the last child in the pgrp, then 1303e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath it ought to wake up and get ECHILD. We would have to 1304e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath search the system for all pid's in the pgrp to be sure. 1305e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1306e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath && (t->waitpid == -1 || 1307e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid)) 1308e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath || (t->waitpid < 0 && t->waitpid == -getpid (t->pid))) 1309e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath */ 1310e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1311e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->parent && 1312e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath (tcp->parent->flags & TCB_SUSPENDED) && 1313e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) { 1314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath error = resume(tcp->parent); 1315e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ++resumed; 1316e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD 1318e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->parent && tcp->parent->nclone_waiting > 0) { 1319e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* Some other threads of our parent are waiting too. */ 1320e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath unsigned int i; 1321e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1322e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* Resume all the threads that were waiting for this PID. */ 1323e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1324e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath struct tcb *t = tcbtab[i]; 1325e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (t->parent == tcp->parent && t != tcp 1326e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 1327e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 1328e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath && t->waitpid == tcp->pid) { 1329e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath error |= resume (t); 1330e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ++resumed; 1331e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1332e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1333e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (resumed == 0) 1334e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* Noone was waiting for this PID in particular, 1335e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath so now we might need to resume some wildcarders. */ 1336e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1337e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath struct tcb *t = tcbtab[i]; 1338e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (t->parent == tcp->parent && t != tcp 1339e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath && ((t->flags 1340e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath & (TCB_CLONE_THREAD|TCB_SUSPENDED)) 1341e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath == (TCB_CLONE_THREAD|TCB_SUSPENDED)) 1342e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath && t->waitpid <= 0 1343e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ) { 1344e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath error |= resume (t); 1345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath break; 1346e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1347e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1349e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 1350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1351bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1360bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig) 136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(pid); 137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp) 137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1388ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1389ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14206d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 14236d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */ 142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 14428f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 14436d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[]; 144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 14458f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 14468f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[]; 14478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif 144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1468bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1475ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv != NULL) 1476ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath free (pollv); 1477c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1478ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv == NULL) { 1479ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath fprintf(stderr, "strace: out of memory for poll vector\n"); 1480ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath exit(1); 1481ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath } 1482ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 1483ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = j = 0; i < tcbtabsize; i++) { 1484ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 14889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 149876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 150076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int arg; 150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) { 151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("F_GETFD"); 151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) { 151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("F_SETFD"); 151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1563bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1564bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1565bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1605bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 1606bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 1607bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1608bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 1609bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 16109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 16269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 16439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 16669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 16789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 1679d870b3c31a0139b335a66a829169bacc74624c44John Hughes struct tcb *in_syscall = NULL; 16809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 16859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(0); 170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 17129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 17139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 17149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 17159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 1716553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 17179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 17189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 17199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 17209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 17219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 17229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 17239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 17249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 17259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 17269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 17279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 17289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 17299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 17309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 17319dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 17329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 17339dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1757b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK 17589dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 1759b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif 176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 1762bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 17639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 1764bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1765bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 1766bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 1767bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 1768bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 1769bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_STATUS (tcp); 1770bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 1771bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 1772553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 1795bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1796bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 1797553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 18082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 18092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 18102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman IOCTL (tcp->pfd, PIOCRUN, 0); 18112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 18122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 1813553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 1814553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 1823bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1824bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 1825bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 1826bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 1827bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 1828bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 1829bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 1830bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 1831bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 1832bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 1834553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */ 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 1837bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 18419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 18429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 1843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 18459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 18469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 18559dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 18569dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 18579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) { 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 1868ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 18705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 18715826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 18725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 18735826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 18745826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 18755826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printtrailer(tcp); 18765826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 18775826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_FAULT)) { 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1887bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1888bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 1889bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman continue; 1890553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 18929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 18969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 1897553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 18989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 1899553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 1900bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) { 1901553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1911e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 1912e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the 1913e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related clone threads with it. This is called in three circumstances: 1914e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent). 1915e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == 0 Continuing TCP will perform an exit_group syscall. 1916e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath SIG == other Continuing TCP with SIG will kill the process. 1917e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/ 1918e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int 1919e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig) 1920e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{ 1921e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* We need to locate our records of all the clone threads 1922e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath related to TCP, either its children or siblings. */ 1923e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD) 1924e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ? tcp->parent 1925e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath : tcp->nclone_detached > 0 1926e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ? tcp : NULL); 1927e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1928e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (sig < 0) { 1929e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (leader != NULL && leader != tcp) 1930e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, 1931e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath "PANIC: handle_group_exit: %d leader %d\n", 1932e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->pid, leader ? leader->pid : -1); 1933e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath droptcb(tcp); /* Already died. */ 1934e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1935e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 1936e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_ATTACHED) { 1937e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (leader != NULL && leader != tcp) { 1938e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* We need to detach the leader so that the 1939e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath process death will be reported to its real 1940e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent. But we kill it first to prevent 1941e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath it doing anything before we kill the whole 1942e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath process in a moment. We can use 1943e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath PTRACE_KILL on a thread that's not already 1944e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath stopped. Then the value we pass in 1945e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath PTRACE_DETACH just sets the death 1946e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath signal reported to the real parent. */ 1947e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_KILL, leader->pid, 0, 0); 1948e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (debug) 1949e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, 1950e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath " [%d exit %d kills %d]\n", 1951e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->pid, sig, leader->pid); 1952e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath detach(leader, sig); 1953e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1954e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath detach(tcp, sig); 1955e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1956e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) { 1957e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath perror("strace: ptrace(PTRACE_CONT, ...)"); 1958e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath cleanup(); 1959e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 1960e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1961e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else { 1962e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (leader != NULL && leader != tcp) 1963e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath droptcb(tcp); 1964e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* The leader will report to us as parent now, 1965e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath and then we'll get to the SIG==-1 case. */ 1966e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 1967e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1968e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1969e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1970e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* Note that TCP and LEADER are no longer valid, 1971e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath but we can still compare against them. */ 1972e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (leader != NULL) { 1973e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath unsigned int i; 1974e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1975e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath struct tcb *t = tcbtab[i]; 1976e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (t != tcp && (t->flags & TCB_CLONE_DETACHED) 1977e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath && t->parent == leader) 1978e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath droptcb(t); 1979e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1980e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 1981e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 1982e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 1983e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath} 1984e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 1985e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 19952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 19962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman static int wait4_options = __WALL; 19972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif 199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while (nprocs != 0) { 200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 20042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 20052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL); 20065bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 20072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 20082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 20092f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman errno = 0; 20102f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, wait4_options, 20112f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman cflag ? &ru : NULL); 20122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 20135bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 20142f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 20152f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, __WCLONE, 20162f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman cflag ? &ru : NULL); 20172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman if (pid == -1) { 20182f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman fprintf(stderr, "strace: clone wait4 " 20192f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman "failed: %s\n", strerror(errno)); 20202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 20212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 20222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else 202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 20242f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */ 202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (wait_errno) { 203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ECHILD: 204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman errno = wait_errno; 205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: wait"); 205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 2065e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX 2066e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (followfork || followvfork) { 2067e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This is needed to go with the CLONE_PTRACE 2068e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath changes in process.c/util.c: we might see 2069e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath the child's initial trap before we see the 2070e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent return from the clone syscall. 2071e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath Leave the child suspended until the parent 2072e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath returns from its system call. Only then 2073e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath will we have the association of parent and 2074e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath child so that we know how to do clearbpt 2075e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in the child. */ 2076e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if ((tcp = alloctcb(pid)) == NULL) { 2077e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, " [tcb table full]\n"); 2078e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath kill(pid, SIGKILL); /* XXX */ 2079e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return 0; 2080e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2081e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED; 2082e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath newoutf(tcp); 2083e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (!qflag) 2084e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "\ 2085e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n", 2086e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath pid); 20878b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 2088e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else 2089e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This can happen if a clone call used 2090e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath CLONE_PTRACE itself. */ 20918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif 2092e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath { 2093e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath fprintf(stderr, "unknown pid: %u\n", pid); 2094e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (WIFSTOPPED(status)) 2095e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2096e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath exit(1); 2097e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */ 210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Apparently, doing any ptrace() call on a stopped 211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process, provokes the kernel to report the process 211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * status again on a subsequent wait(), even if the 211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process has not been actually restarted. 211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Since we have inspected the arguments of suspended 211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * processes we end up here testing for this case. 211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 21232efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath tprintf("+++ killed by %s %s+++", 21242efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 21252efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP 21262efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath WCOREDUMP(status) ? "(core dumped) " : 21272efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 21282efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath ""); 212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2131e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2132e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2133e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2135e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u exited\n", pid); 214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "PANIC: attached pid %u exited\n", 214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 21450a396906981a03f93c07cb912585d0679dd50899Roland McGrath if (tcp == tcp_last) { 21460a396906981a03f93c07cb912585d0679dd50899Roland McGrath if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) 21470a396906981a03f93c07cb912585d0679dd50899Roland McGrath == TCB_INSYSCALL) 21480a396906981a03f93c07cb912585d0679dd50899Roland McGrath tprintf(" <unfinished ... exit status %d>\n", 21490a396906981a03f93c07cb912585d0679dd50899Roland McGrath WEXITSTATUS(status)); 21500a396906981a03f93c07cb912585d0679dd50899Roland McGrath tcp_last = NULL; 21510a396906981a03f93c07cb912585d0679dd50899Roland McGrath } 2152e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2153e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, -1); 2154e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 2156e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 2166ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_STARTUP) { 216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) { 217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interestingly, the process may stop 217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * with STOPSIG equal to some other signal 217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * than SIGSTOP if we happend to attach 218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * just before the process takes a signal. 218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "pid %u not stopped\n", pid); 218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* A child of us stopped at exec */ 219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGTRAP && followvfork) 219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fixvfork(tcp); 219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) { 219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) != SIGTRAP) { 220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, 221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid, (char *) 1, 0) < 0) { 221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 22247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman unsigned long addr = 0, pc = 0; 22257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#ifdef PT_GETSIGINFO 22267b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# define PSR_RI 41 22277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman struct siginfo si; 22287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman unsigned long psr; 22297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 22307b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman upeek(pid, PT_CR_IPSR, &psr); 22317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman upeek(pid, PT_CR_IIP, &pc); 22327b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 22337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 22347b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman ptrace(PT_GETSIGINFO, pid, 0, (long) &si); 22357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman addr = (unsigned long) si.si_addr; 22367b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 22387b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman tprintf("--- %s (%s) @ %lx (%lx) ---", 2239ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WSTOPSIG(status)), 22407b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman strsignal(WSTOPSIG(status)), pc, addr); 224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_ATTACHED) && 224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath handle_group_exit(tcp, WSTOPSIG(status)); 2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else 224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman WSTOPSIG(status)) < 0) { 225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_KILL, 226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, SIGTERM); 226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 2272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING 2273e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (tcp->flags & TCB_GROUP_EXITING) { 2274e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (handle_group_exit(tcp, 0) < 0) 2275e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath return -1; 2276e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath continue; 2277e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 2278e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif 227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) { 228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_CONT, ...)"); 228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) { 229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2303bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol; 230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b) 231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h> 231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a) 231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist) 232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt; 232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl 232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 232476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman VA_START(args, fmt); 2327b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (outf) { 2328b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath int n = vfprintf(outf, fmt, args); 2329b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (n < 0 && outf != stderr) 2330b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath perror(outfname == NULL 2331b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath ? "<writing to pipe>" : outfname); 2332b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath else 2333b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath curcol += n; 2334b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath } 233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp) 234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) { 234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last->flags |= TCB_REPRINT; 234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 235676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 235776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 236076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 236776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 236876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 237476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 238176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp) 239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 23989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2399ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 24009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 24019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) { 24029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 24039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 24049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 2405553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 24069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 24079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 24089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 24099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 24109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 24119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 24129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 2413553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 24149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return writev (fd, iov, n); 24159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 24169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 24179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2418