strace.c revision 04f8b4860f12512186481ca21dbd311d9d612326
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* 276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved. 776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without 976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions 1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met: 1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright 1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer. 1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright 1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer in the 1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * documentation and/or other materials provided with the distribution. 1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products 1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * derived from this software without specific prior written permission. 1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * $Id$ 3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h" 3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h> 363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h> 3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h> 3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h> 3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h> 4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h> 4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h> 4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h> 4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h> 4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h> 4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h> 4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h> 4719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h> 4870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h> 4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX 51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h> 5244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# if defined __NR_tkill 5344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig)) 54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else 55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath /* kill() may choose arbitrarily the target task of the process group 56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath while we later wait on a that specific TID. PID process waits become 57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath TID task specific waits for a process under ptrace(2). */ 58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!" 5944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# define my_tkill(tid, sig) kill((tid), (sig)) 60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif 61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif 62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath 637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX) 647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 67bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h> 69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 73ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H 759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 781d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif 7996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ; 80418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind; 81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg; 8296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko 8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8441c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0; 85f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0; 863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */ 8775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP; 88e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0; 89e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE; 90b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0; 91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/* 92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option. 93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice. 94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's, 95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process 96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild 97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID. 98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases 99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals, 100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between, 101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link. 102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0; 10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */ 10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0; 10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig 1088a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */ 1098a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0; 1108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards 1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */ 1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0; 1138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards 114a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0; 115a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0; 11675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0; 117eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 118b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL; 119ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid; 120ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid; 12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 124b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL; 125ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf; 126ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol; 127ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab; 1282b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize; 129ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname; 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 131e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig); 132e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void); 133e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void); 134e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig); 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd); 146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig); 147e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void); 148ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv; 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 152e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void); 153e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd); 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 174cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval) 17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 1778a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\ 178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\ 1798a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards [-P path] [command [arg ...]]\n\ 180b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\ 181de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath [command [arg ...]]\n\ 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 183b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\ 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 1928a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\ 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 199ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\ 20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 203de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\ 204de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\ 2058a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\ 206de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it 20717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\ 208de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath */ 209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 21375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn)); 21475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) 21575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 21675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (strace_tracer_pid == getpid()) { 21775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko cflag = 0; 21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko cleanup(); 21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko } 22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko exit(1); 22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p) 2243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{ 22544d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin fflush(NULL); 22644d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin fprintf(stderr, "%s: ", progname); 22744d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin vfprintf(stderr, fmt, p); 22844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin if (err_no) 22944d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin fprintf(stderr, ": %s\n", strerror(err_no)); 23044d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin else 23144d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin putc('\n', stderr); 23244d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin fflush(stderr); 23375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 23475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 23575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...) 23675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 23775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(0, fmt, p); 2403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko va_end(p); 24175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 2423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...) 24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(0, fmt, p); 24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko die(); 24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...) 25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(errno, fmt, p); 25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_end(p); 25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko} 25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...) 26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{ 26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_list p; 26275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko va_start(p, fmt); 26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko verror_msg(errno, fmt, p); 26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko die(); 2653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko} 2663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 276c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */ 277c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK 278c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0 279c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else 280c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1 281c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork() vfork() 282c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif 283c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger 2841f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void 28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd) 28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 2871f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko int flags, newflags; 2881f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko 2891f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko flags = fcntl(fd, F_GETFD); 2901f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko if (flags < 0) { 2911f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko /* Can happen only if fd is bad. 2921f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko * Should never happen: if it does, we have a bug 2931f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko * in the caller. Therefore we just abort 2941f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko * instead of propagating the error. 2951f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko */ 2961f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko perror_msg_and_die("fcntl(%d, F_GETFD)", fd); 29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newflags = flags | FD_CLOEXEC; 30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (flags == newflags) 3011f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko return; 30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko fcntl(fd, F_SETFD, newflags); /* never fails */ 30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids 30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations. 30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void 31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void) 31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4 31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin int euid = geteuid(), uid = getuid(); 31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3167b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko if (euid != uid && setreuid(euid, uid) < 0) { 317cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("setreuid"); 31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3224bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE 3234bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64 3244bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else 3254bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen 3264bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif 3274bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath 32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 3293d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path) 33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin FILE *fp; 33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 3343d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko fp = fopen_for_output(path, "w"); 3353d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko if (!fp) 3363d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko perror_msg_and_die("Can't fopen '%s'", path); 33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 3383d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko set_cloexec_flag(fileno(fp)); 33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin return fp; 34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3427dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0; 34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL 34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh" 34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif 34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/* 34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish 35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3) 35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid. 35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */ 35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE * 35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command) 35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 3567dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko FILE *fp; 3577dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko int fds[2]; 35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin swap_uid(); 36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pipe(fds) < 0) 3617dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko perror_msg_and_die("pipe"); 36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3637dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko set_cloexec_flag(fds[1]); /* never fails */ 36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3657dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko popen_pid = vfork(); 3667dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko if (popen_pid == -1) 3677dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko perror_msg_and_die("vfork"); 36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3697dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko if (popen_pid == 0) { 37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin /* child */ 37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin close(fds[1]); 3727dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko if (fds[0] != 0) { 3737dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko if (dup2(fds[0], 0)) 3747dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko perror_msg_and_die("dup2"); 3757dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko close(fds[0]); 37610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin execl(_PATH_BSHELL, "sh", "-c", command, NULL); 3787dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL); 37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 3807dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko 3817dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko /* parent */ 3827dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko close(fds[0]); 3837dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko swap_uid(); 3847dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko fp = fdopen(fds[1], "w"); 3857dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko if (!fp) 3867dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko error_msg_and_die("Out of memory"); 3877dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko return fp; 38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 38910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 3903d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void 39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp) 39210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{ 39310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (outfname && followfork > 1) { 3947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char name[520 + sizeof(int) * 3]; 3957a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko sprintf(name, "%.512s.%u", outfname, tcp->pid); 3963d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko tcp->outf = strace_fopen(name); 39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin} 39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin 40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void) 40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tcbi; 40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Block user interruptions as we would leave the traced 40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * process stopped (process state T) if we would terminate in 40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * between PTRACE_ATTACH and wait4 () on SIGSTOP. 410b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko * We rely on cleanup() from this point on. 41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 415ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 416ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid_t pid = fork(); 417ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 418ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(1); 419ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 420ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid) { /* parent */ 421ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 42275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko * Wait for grandchild to attach to straced process 42375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko * (grandparent). Grandchild SIGKILLs us after it attached. 42475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko * Grandparent's wait() is unblocked by our death, 425ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * it proceeds to exec the straced program. 426ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 427ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pause(); 428ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko _exit(0); /* paranoia */ 429ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 43075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* grandchild */ 43175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* We will be the tracer process. Remember our new pid: */ 43275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko strace_tracer_pid = getpid(); 433ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 434ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp = tcbtab[tcbi]; 43744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko 43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX 44144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (tcp->flags & TCB_ATTACH_DONE) 44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif 44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Reinitialize the output since it may have changed. */ 44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->outf = outf; 4463d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko newoutf(tcp); 44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (proc_open(tcp, 1) < 0) { 45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, "trouble opening proc file\n"); 45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX 456ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (followfork && !daemonized_tracer) { 4577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; 45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath DIR *dir; 45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sprintf(procdir, "/proc/%d/task", tcp->pid); 46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath dir = opendir(procdir); 46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (dir != NULL) { 46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath unsigned int ntid = 0, nerr = 0; 46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct dirent *de; 46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int tid; 46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath while ((de = readdir(dir)) != NULL) { 4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (de->d_fileno == 0) 46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tid = atoi(de->d_name); 47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tid <= 0) 47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++ntid; 473f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) { 47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath ++nerr; 475f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko if (debug) 476f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko fprintf(stderr, "attach to pid %d failed\n", tid); 477f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko } 478f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko else { 479f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko if (debug) 480f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko fprintf(stderr, "attach to pid %d succeeded\n", tid); 48144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (tid != tcp->pid) { 48244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko struct tcb *new_tcp = alloctcb(tid); 48344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE; 484f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko } 48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 486aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (interactive) { 487aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko sigprocmask(SIG_SETMASK, &empty_set, NULL); 488aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko if (interrupted) 48944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko goto ret; 490aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko sigprocmask(SIG_BLOCK, &blocked_set, NULL); 491aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko } 49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath closedir(dir); 4947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko ntid -= nerr; 4957a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if (ntid == 0) { 49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) { 5017a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko fprintf(stderr, ntid > 1 5027a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n" 5037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n", 50444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko tcp->pid, ntid); 50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 5077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (opendir worked) */ 5087a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko } /* if (-f) */ 50944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# endif /* LINUX */ 51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath perror("attach: ptrace(PTRACE_ATTACH, ...)"); 51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath droptcb(tcp); 51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 515f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko if (debug) 516f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid); 517ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 518ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 519ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 520ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It is our grandparent we trace, not a -p PID. 521ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Don't want to just detach on exit, so... 522ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 523ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags &= ~TCB_ATTACHED; 524ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 525ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make parent go away. 526ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Also makes grandparent's wait() unblock. 527ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 528ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(getppid(), SIGKILL); 529ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 530ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!qflag) 53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath fprintf(stderr, 53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath "Process %u attached - interrupt to quit\n", 53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath tcp->pid); 536f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko } /* for each tcbtab[] */ 53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 53844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret: 53944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#ifdef LINUX 54044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko /* TCB_ATTACH_DONE flag is used only in this function */ 54144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko for (tcbi = 0; tcbi < tcbtabsize; tcbi++) { 54244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko tcp = tcbtab[tcbi]; 54344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko tcp->flags &= ~TCB_ATTACH_DONE; 54444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko } 54544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#endif 54644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko 54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interactive) 54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void 5521201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv) 55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{ 55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct stat statbuf; 55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath const char *filename; 55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath char pathname[MAXPATHLEN]; 55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int pid = 0; 55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath struct tcb *tcp; 55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath filename = argv[0]; 56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(filename, '/')) { 56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strlen(filename) > sizeof pathname - 1) { 56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath errno = ENAMETOOLONG; 564cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("exec"); 56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC 56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Debuggers customarily check the current directory 57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * first regardless of the path but doing that gives 57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * security geeks a panic attack. 57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (stat(filename, &statbuf) == 0) 57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname, filename); 57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */ 57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 57830145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin const char *path; 57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath int m, n, len; 58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath for (path = getenv("PATH"); path && *path; path += m) { 58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (strchr(path, ':')) { 58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath n = strchr(path, ':') - path; 58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n + 1; 58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath m = n = strlen(path); 58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (n == 0) { 58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (!getcwd(pathname, MAXPATHLEN)) 59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = strlen(pathname); 59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else if (n > sizeof pathname - 1) 59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath continue; 59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else { 59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strncpy(pathname, path, n); 59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath len = n; 59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (len && pathname[len - 1] != '/') 60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pathname[len++] = '/'; 60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath strcpy(pathname + len, filename); 60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) == 0 && 60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Accept only regular files 60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath with some execute bits set. 60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath XXX not perfect, might still fail */ 60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath S_ISREG(statbuf.st_mode) && 60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath (statbuf.st_mode & 0111)) 60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath break; 60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (stat(pathname, &statbuf) < 0) { 612cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("Can't stat '%s'", filename); 61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 614a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin strace_child = pid = fork(); 615ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pid < 0) { 616cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("fork"); 617ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 61875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */ 61975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */ 620ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko ) { 621ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko pid = getpid(); 62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 623b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (outf != stderr) close(fileno(outf)); 62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS 62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* Kludge for SGI, see proc_open for details. */ 62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_handler = foobar; 62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sa.sa_flags = 0; 62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigemptyset(&sa.sa_mask); 62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath sigaction(SIGINT, &sa, NULL); 63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */ 63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD 63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath pause(); 63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */ 634ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); /* stop HERE */ 63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */ 63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */ 637b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (outf != stderr) 638b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko close(fileno(outf)); 63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 640ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 642cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)"); 643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (debug) 645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko kill(pid, SIGSTOP); 64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 64702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 64802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL || geteuid() == 0) { 64902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath uid_t run_euid = run_uid; 65002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath gid_t run_egid = run_gid; 65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISUID) 65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_euid = statbuf.st_uid; 65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (statbuf.st_mode & S_ISGID) 65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath run_egid = statbuf.st_gid; 65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * It is important to set groups before we 65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * lose privileges on setuid. 66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (username != NULL) { 66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (initgroups(username, run_gid) < 0) { 663cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("initgroups"); 66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setregid(run_gid, run_egid) < 0) { 666cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("setregid"); 66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (setreuid(run_uid, run_euid) < 0) { 669cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("setreuid"); 67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath setreuid(run_uid, run_uid); 67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (!daemonized_tracer) { 677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Induce an immediate stop so that the parent 679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will resume us with PTRACE_SYSCALL and display 680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * this execve call normally. 681c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * Unless of course we're on a no-MMU system where 682c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * we vfork()-ed, so we cannot stop the child. 683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 684c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger if (!strace_vforked) 685c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger kill(getpid(), SIGSTOP); 686ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } else { 687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko struct sigaction sv_sigchld; 688ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko sigaction(SIGCHLD, NULL, &sv_sigchld); 689ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 690ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Make sure it is not SIG_IGN, otherwise wait 691ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * will not block. 692ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 693ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko signal(SIGCHLD, SIG_DFL); 694ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* 695ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Wait for grandchild to attach to us. 696ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * It kills child after that, and wait() unblocks. 697ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */ 698ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko alarm(3); 699ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko wait(NULL); 700ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko alarm(0); 701ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko sigaction(SIGCHLD, &sv_sigchld, NULL); 702ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */ 70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 70502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath execv(pathname, argv); 706cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("exec"); 70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 708ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko 709ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* We are the tracer. */ 71075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* With -D, we are *child* here, IOW: different pid. Fetch it. */ 71175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko strace_tracer_pid = getpid(); 71275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 713ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp = alloctcb(daemonized_tracer ? getppid() : pid); 714ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (daemonized_tracer) { 715ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko /* We want subsequent startup_attach() to attach to it. */ 716ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko tcp->flags |= TCB_ATTACHED; 717ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko } 71802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS 719ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (proc_open(tcp, 0) < 0) { 720cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("trouble opening proc file"); 72102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath } 722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */ 72302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath} 72402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 725b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX 72604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void kill_save_errno(pid_t pid, int sig) 72704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin{ 72804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin int saved_errno = errno; 72904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin 73004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin (void) kill(pid, sig); 73104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin errno = saved_errno; 73204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin} 73304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin 734b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/* 735b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options. 736b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it, 737b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel. 738b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */ 73904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void 7403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void) 741b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{ 7422fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin int pid, expected_grandchild = 0, found_grandchild = 0; 7432fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin const unsigned int test_options = PTRACE_O_TRACECLONE | 7442fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin PTRACE_O_TRACEFORK | 7452fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin PTRACE_O_TRACEVFORK; 746b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 747b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao if ((pid = fork()) < 0) 74804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("fork"); 749b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao else if (pid == 0) { 75004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin pid = getpid(); 75104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) 75204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", 75304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__); 75404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill(pid, SIGSTOP); 75504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (fork() < 0) 75604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("fork"); 75704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin _exit(0); 758b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 759b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin 760b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin while (1) { 761b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin int status, tracee_pid; 762b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin 76304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin errno = 0; 764b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin tracee_pid = wait(&status); 76504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid <= 0) { 766b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (errno == EINTR) 767b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin continue; 768b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin else if (errno == ECHILD) 769b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao break; 77004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 77104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: unexpected wait result %d", 77204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, tracee_pid); 77304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 77404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WIFEXITED(status)) { 77504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WEXITSTATUS(status)) { 77604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid != pid) 77704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 77804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected exit status %u", 77904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WEXITSTATUS(status)); 78004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 78104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin continue; 78204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 78304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WIFSIGNALED(status)) { 78404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid != pid) 78504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 78604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected signal %u", 78704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WTERMSIG(status)); 78804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 78904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (!WIFSTOPPED(status)) { 79004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (tracee_pid != pid) 79104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(tracee_pid, SIGKILL); 79204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill(pid, SIGKILL); 79304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected wait status %x", 79404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, status); 795b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 796b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin if (tracee_pid != pid) { 7972fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin found_grandchild = tracee_pid; 79804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) { 79904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(tracee_pid, SIGKILL); 80004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 80104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("PTRACE_CONT doesn't work"); 80204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 80304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin continue; 804b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin } 80504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin switch (WSTOPSIG(status)) { 80604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin case SIGSTOP: 80704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0 80804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin && errno != EINVAL && errno != EIO) 80904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg("PTRACE_SETOPTIONS"); 81004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin break; 81104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin case SIGTRAP: 81204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (status >> 16 == PTRACE_EVENT_FORK) { 81304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin long msg = 0; 8142fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin 81504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_GETEVENTMSG, pid, 81604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin NULL, (long) &msg) == 0) 81704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin expected_grandchild = msg; 818b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 81904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin break; 82004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 82104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { 82204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 82304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 824b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 825b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao } 82604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (expected_grandchild && expected_grandchild == found_grandchild) { 827f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko ptrace_setoptions |= test_options; 82804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (debug) 82904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin fprintf(stderr, "ptrace_setoptions = %#x\n", 83004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin ptrace_setoptions); 83104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin return; 83204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 83304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg("Test for PTRACE_O_TRACECLONE failed, " 83404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin "giving up using this feature."); 835b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao} 8363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 8373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* 8383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD. 8393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it, 8403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80). 8413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * 8423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs, 8433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86: 8443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start: .globl _start 8453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * int3 8463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * movl $42, %ebx 8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * movl $1, %eax 8483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * int $0x80 8493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S") 8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */ 8513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void 8523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void) 8533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{ 85404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin const unsigned int test_options = PTRACE_O_TRACESYSGOOD | 85504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin PTRACE_O_TRACEEXEC; 8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko int pid; 8573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko int it_worked = 0; 8583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko pid = fork(); 8603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (pid < 0) 86175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko perror_msg_and_die("fork"); 8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (pid == 0) { 8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko pid = getpid(); 8653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) 86675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko /* Note: exits with exitcode 1 */ 86704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", 86804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__); 8693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko kill(pid, SIGSTOP); 8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko _exit(0); /* parent should see entry into this syscall */ 8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko while (1) { 8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko int status, tracee_pid; 8753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 8763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko errno = 0; 8773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko tracee_pid = wait(&status); 8783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (tracee_pid <= 0) { 8793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (errno == EINTR) 8803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko continue; 88104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 88204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg_and_die("%s: unexpected wait result %d", 88304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, tracee_pid); 88475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko } 88575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (WIFEXITED(status)) { 88675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (WEXITSTATUS(status) == 0) 88775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko break; 88804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected exit status %u", 88904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WEXITSTATUS(status)); 89004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin } 89104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (WIFSIGNALED(status)) { 89204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected signal %u", 89304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, WTERMSIG(status)); 8943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 8953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (!WIFSTOPPED(status)) { 8963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko kill(pid, SIGKILL); 89704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg_and_die("%s: unexpected wait status %x", 89804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin __func__, status); 8993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 9003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (WSTOPSIG(status) == SIGSTOP) { 9013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko /* 9023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * We don't check "options aren't accepted" error. 9033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * If it happens, we'll never get (SIGTRAP | 0x80), 9043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and thus will decide to not use the option. 9053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * IOW: the outcome of the test will be correct. 9063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */ 90704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0 90804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin && errno != EINVAL && errno != EIO) 90904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin perror_msg("PTRACE_SETOPTIONS"); 9103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 9113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (WSTOPSIG(status) == (SIGTRAP | 0x80)) { 9123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko it_worked = 1; 9133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 9143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) { 91504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin kill_save_errno(pid, SIGKILL); 91675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko perror_msg_and_die("PTRACE_SYSCALL doesn't work"); 9173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 9183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 9193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 9203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (it_worked) { 92175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko syscall_trap_sig = (SIGTRAP | 0x80); 922f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko ptrace_setoptions |= test_options; 9233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (debug) 924f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko fprintf(stderr, "ptrace_setoptions = %#x\n", 925f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko ptrace_setoptions); 9263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko return; 9273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 9283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko 92904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin error_msg("Test for PTRACE_O_TRACESYSGOOD failed, " 93004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin "giving up using this feature."); 9313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko} 932b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif 933b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 93508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[]) 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 93906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin int optF = 0; 94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 94208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin progname = argv[0] ? argv[0] : "strace"; 94308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin 94475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko strace_tracer_pid = getpid(); 94575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko 946ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath /* Allocate the initial tcbtab. */ 947ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcbtabsize = argc; /* Surely enough for all -p args. */ 9484f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0])); 949cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko if (tcbtab == NULL) 950cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Out of memory"); 9514f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko tcp = calloc(tcbtabsize, sizeof(*tcp)); 9524f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko if (tcp == NULL) 953cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Out of memory"); 9544f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko for (c = 0; c < tcbtabsize; c++) 9554f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko tcbtab[c] = tcp++; 956ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 959138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_sortby(DEFAULT_SORTBY); 960138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath set_personality(DEFAULT_PERSONALITY); 96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 9668a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards "+cCdfFhiqrtTvVxyz" 967ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 968ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko "D" 969ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 9708a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards "a:e:o:O:p:s:S:u:E:P:")) != EOF) { 97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 973e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_BOTH) { 974cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("-c and -C are mutually exclusive options"); 975e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 976e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_ONLY_STATS; 977e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin break; 978e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin case 'C': 979e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag == CFLAG_ONLY_STATS) { 980cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("-c and -C are mutually exclusive options"); 981e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin } 982e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin cflag = CFLAG_BOTH; 98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 987ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS 988ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko case 'D': 989ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko daemonized_tracer = 1; 990ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko break; 991ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif 99241c48227a86a176da333f713d5047240885f25ccRoland McGrath case 'F': 99306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin optF = 1; 99406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin break; 99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 10208a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards case 'y': 10218a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards show_fd_path = 1; 10228a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards break; 102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 10279c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath printf("%s -- version %s\n", PACKAGE_NAME, VERSION); 102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 103017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig case 'z': 103117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig not_failing_only = 1; 103217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig break; 103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 1046de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if ((pid = atoi(optarg)) <= 0) { 1047cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg("Invalid process id: '%s'", optarg); 104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 105075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (pid == strace_tracer_pid) { 1051cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg("I'm sorry, I can't let you do that, Dave."); 105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1054418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloc_tcb(pid, 0); 105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 10588a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards case 'P': 10598a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards tracing_paths = 1; 10608a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards if (pathtrace_select(optarg)) { 1061cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Failed to select path '%s'", optarg); 10628a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards } 10638a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards break; 106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 1066dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath if (max_strlen < 0) { 1067cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Invalid -s argument: '%s'", optarg); 1068dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath } 106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1076de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath case 'E': 1077de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath if (putenv(optarg) < 0) { 1078cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Out of memory"); 1079de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath } 1080de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath break; 108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1087d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath if ((optind == argc) == !pflag_seen) 1088ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath usage(stderr, 1); 1089ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath 1090d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao if (pflag_seen && daemonized_tracer) { 1091cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("-D and -p are mutually exclusive options"); 1092d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao } 1093d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao 109406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin if (!followfork) 109506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin followfork = optF; 109606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin 1097cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath if (followfork > 1 && cflag) { 1098cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("(-c or -C) and -ff are mutually exclusive options"); 1099cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath } 1100cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath 110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 1106cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("You must be root to use the -u option"); 110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 1109cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Cannot find user '%s'", username); 111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11198044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX 112004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin if (followfork) 112104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin test_ptrace_setoptions_followfork(); 11223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko test_ptrace_setoptions_for_all(); 11238044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif 11248044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 112737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* See if they want to pipe the output. */ 112837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname[0] == '|' || outfname[0] == '!') { 112937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath /* 113037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * We can't do the <outfname>.PID funny business 113137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath * when using popen, so prohibit it. 113237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath */ 11337dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko if (followfork > 1) 11347dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko error_msg_and_die("Piping the output and -ff are mutually exclusive"); 11357dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko outf = strace_popen(outfname + 1); 113654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 11373d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko else if (followfork <= 1) 11383d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko outf = strace_fopen(outfname); 113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1141cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko if (!outfname || outfname[0] == '|' || outfname[0] == '!') { 1142cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko static char buf[BUFSIZ]; 114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 1144cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko } 114537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath if (outfname && optind < argc) { 114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 1148369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath } 1149b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao 115054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* Valid states here: 115154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath optind < argc pflag_seen outfname interactive 115254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 0 1 115354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 0 1 115454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 1 0 1 0 115554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 0 1 1 1 115654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath */ 115754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath 115854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath /* STARTUP_CHILD must be called before the signal handlers get 115954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath installed below as they are inherited into the spawned process. 116054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath Also we do not need to be protected by them as during interruption 116154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath in the STARTUP_CHILD mode we kill the spawned process anyway. */ 116254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath if (!pflag_seen) 116354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath startup_child(&argv[optind]); 116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 1189bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 1192553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 1193553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath /* Make sure SIGCHLD has the default action so that waitpid 1194553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath definitely works without losing track of children. The user 1195553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath should not have given us a bogus state to inherit, but he might 1196553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath have. Arguably we should detect SIG_IGN here and pass it on 1197553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath to children, but probably noone really needs that. */ 1198553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sa.sa_handler = SIG_DFL; 1199553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath sigaction(SIGCHLD, &sa, NULL); 1200bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1202ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko if (pflag_seen || daemonized_tracer) 120302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath startup_attach(); 120402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath 120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 1208a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin fflush(NULL); 1209a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (exit_code > 0xff) { 1210a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Child was killed by a signal, mimic that. */ 1211a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code &= 0xff; 1212a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin signal(exit_code, SIG_DFL); 1213a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin raise(exit_code); 1214a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin /* Paranoia - what if this signal is not fatal? 1215a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin Exit with 128 + signo then. */ 1216a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code += 128; 1217a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin } 1218a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit(exit_code); 121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12212b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void 1222418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void) 12237b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{ 12247b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath /* Allocate some more TCBs and expand the table. 12257b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath We don't want to relocate the TCBs because our 12267b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath callers have pointers and it would be a pain. 12277b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath So tcbtab is a table of pointers. Since we never 12287b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath free the TCBs, we allocate a single chunk of many. */ 122918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko int i = tcbtabsize; 123018da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0])); 123118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0])); 123218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko if (newtab == NULL || newtcbs == NULL) 123318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko error_msg_and_die("expand_tcbtab: out of memory"); 12347b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtabsize *= 2; 12357b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath tcbtab = newtab; 123618da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko while (i < tcbtabsize) 123718da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko tcbtab[i++] = newtcbs++; 12387b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath} 12397b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath 124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 124110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed) 124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1246418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko if (nprocs == tcbtabsize) 1247418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko expand_tcbtab(); 1248418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko 1249ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1250ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 125218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko memset(tcp, 0, sizeof(*tcp)); 125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 12581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (debug) 12591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs); 126010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (command_options_parsed) 126110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin newoutf(tcp); 126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 126518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko error_msg_and_die("bug in alloc_tcb"); 126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1268bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 1270418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching) 127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 1274bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 127519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 127619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1284ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 12859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 12869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 12879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 12889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 12899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 12909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 12911f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko set_cloexec_flag(tcp->pfd); 12929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 12939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 12949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 12959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 12969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 12971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko set_cloexec_flag(tcp->pfd_stat); 12989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 12999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 13009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 13019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 13029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 13031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko set_cloexec_flag(tcp->pfd_as); 13049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 1306bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 1308372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab tcp->pfd = open(proc, O_RDWR|O_EXCL); 1309bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1310bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 1311372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab tcp->pfd = open(proc, O_RDWR); 1312bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 1313372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab if (tcp->pfd < 0) { 131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 13171f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko set_cloexec_flag(tcp->pfd); 13189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 1319bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1320bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 1321bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 1322bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 1323bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1324bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 1326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 1327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 1328bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 1329bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1330bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1331bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1332bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1333bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1341b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (IOCTL_STATUS(tcp) < 0) { 134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 13459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 1346cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko break; 134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1349bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 135116a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1355553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 13599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 13659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 1370553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 1381bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 13835ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko return -1; 1384bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1385bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 1386bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 13875ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko perror("PIOCSFL"); 13885ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko return -1; 1389bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1390bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 1392bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 139319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 139419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 139519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 139619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 1397b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i); 139819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 1399b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko praddset(&syscalls, SYS_execve); 140019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 1401b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko praddset(&syscalls, SYS_fork); 140219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 1403b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko praddset(&syscalls, SYS_forkall); 140419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 1405553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1 1406b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko praddset(&syscalls, SYS_fork1); 140719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 140819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 1409b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko praddset(&syscalls, SYS_rfork1); 141019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 141119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 1412b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko praddset(&syscalls, SYS_rforkall); 141319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 141419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 141519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 141919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 142019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 142419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 142519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 142619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 142719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 1428b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i); 142919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 14309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 143419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 143519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 143619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 143719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 1438b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i); 143919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 14409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1444bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1445bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 1446b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko arg = S_SIG | S_SCE | S_SCX; 1447b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 1448bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 1449bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 1450bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1451bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 1460553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT 146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 14629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 1463b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1467553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 1468bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 1469bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1470bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 1471bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1472553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 1475b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (IOCTL_WSTOP(tcp) < 0) { 147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 14799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 1480bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 1481bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 148276989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath if (known_scno(tcp) == SYS_execve) 148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 1486bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 14879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 14889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 1489bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1490bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 1491553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1495bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1496bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 1497bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 1498bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 1501553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1503bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1505bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1506bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 1507553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath if (attaching < 2) { 15082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 15092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 15102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 15112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 15122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 15132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 15142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 1515553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 15162e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 15172e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 15182e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 15192e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 15202e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 15212e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 15222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 15232e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 15242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 15252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 15262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 15272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 15282e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 15292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 15302e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 15312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 1532bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1533bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1547bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1549e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb * 155054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid) 155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 155354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 155454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (pid <= 0) 155554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return NULL; 155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1557ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 155854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath struct tcb *tcp = tcbtab[i]; 155954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (tcp->pid == pid && (tcp->flags & TCB_INUSE)) 156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 156254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1566bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 156954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void) 157054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{ 157154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath int i; 157254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath struct tcb *tcp; 157354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath for (i = 0; i < tcbtabsize; i++) { 157454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath tcp = tcbtab[i]; 157554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath if (tcp->flags & TCB_INUSE) 157654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return tcp; 157754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath } 157854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath return NULL; 157954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath} 158054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath 158154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb * 15821201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd) 158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1586ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = 0; i < tcbtabsize; i++) { 1587ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1596bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 15991201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp) 160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 160319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko 160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 16051d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (debug) 16061d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs); 1607eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 1611bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1612bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 1613bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 1614bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 1615bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1616bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 1617bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 1618bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 1619bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 1620553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */ 1621bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 162219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko tcp->flags = 0; /* rebuild_pollv needs it */ 162319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko rebuild_pollv(); 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1626eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 1627822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman if (outfname && followfork > 1 && tcp->outf) 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 1629eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman 163019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko memset(tcp, 0, sizeof(*tcp)); 163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16330a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig 16340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath Never call DETACH twice on the same process as both unattached and 16350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath attached-unstopped processes give the same ESRCH. For unattached process we 16360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath would SIGSTOP it and wait for its SIGSTOP notification forever. */ 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 16391201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig) 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 1642ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX 16431bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath int status, catch_sigstop; 1644ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 1647840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab clearbpt(tcp); 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 16527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * before detaching. Arghh. We go through hoops 16537bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath * to make a clean break of things. 165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 16557bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC) 16567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH 16577bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH 16587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif 165902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 166002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the 166102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * expected SIGSTOP. We must catch exactly one as otherwise the 166202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * detached process would be left stopped (process state T). 166302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 166402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = (tcp->flags & TCB_STARTUP); 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 16677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 16687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath else if (errno != ESRCH) { 16697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath /* Shouldn't happen. */ 16707bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: ptrace(PTRACE_DETACH, ...)"); 16717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 167244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko else if (my_tkill(tcp->pid, 0) < 0) { 16737bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 16747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: checking sanity"); 16757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 167644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) { 16777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath if (errno != ESRCH) 16787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath perror("detach: stopping child"); 16797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath } 168002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath else 168102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath catch_sigstop = 1; 1682ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (catch_sigstop) { 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 16847508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 16857508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WALL, NULL) < 0) { 16867508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno == ECHILD) /* Already gone. */ 16877508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16887508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != EINVAL) { 168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 16907508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16917508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16927508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */ 16937508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* No __WALL here. */ 16947508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (waitpid(tcp->pid, &status, 0) < 0) { 16957508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) { 16967508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 16977508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 16987508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 16997508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE 17007508cb4678141d146d819120f6b5b428c103882eRoland McGrath /* If no processes, try clones. */ 17017508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (wait4(tcp->pid, &status, __WCLONE, 17027508cb4678141d146d819120f6b5b428c103882eRoland McGrath NULL) < 0) { 17037508cb4678141d146d819120f6b5b428c103882eRoland McGrath if (errno != ECHILD) 17047508cb4678141d146d819120f6b5b428c103882eRoland McGrath perror("detach: waiting"); 17057508cb4678141d146d819120f6b5b428c103882eRoland McGrath break; 17067508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 17077508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */ 17087508cb4678141d146d819120f6b5b428c103882eRoland McGrath } 17097508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 17117508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif 171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 1717732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko ptrace_restart(PTRACE_DETACH, tcp, sig); 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1720732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_CONT, tcp, 172175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko WSTOPSIG(status) == syscall_trap_sig ? 0 1722732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko : WSTOPSIG(status)); 1723732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (error < 0) 172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 1726ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } 17277bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */ 172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 1734732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko error = ptrace_restart(PTRACE_DETACH, tcp, sig); 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 1741a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath 174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1745bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1747e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig) 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1756bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 17591201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void) 176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1764ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath for (i = 0; i < tcbtabsize; i++) { 1765ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath tcp = tcbtab[i]; 176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 1773ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko tprintf(" <unfinished ...>"); 1774ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 17881201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig) 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17956d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST 179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 17986d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */ 179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 18011201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no) 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 180535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko if (err_no < 1 || err_no >= sys_nerr) { 180635aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko sprintf(buf, "Unknown error %d", err_no); 180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 180935aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko return sys_errlist[err_no]; 181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18168f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST 18176d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[]; 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 18198f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST 18208f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[]; 18218f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif 182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 18241201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig) 182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 18441201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void) 184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1848ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv != NULL) 1849b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko free(pollv); 1850c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]); 1851ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath if (pollv == NULL) { 1852cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Out of memory"); 1853ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath } 1854ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath 1855ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath for (i = j = 0; i < tcbtabsize; i++) { 1856ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath struct tcb *tcp = tcbtab[i]; 185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 18609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 1864cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("proc miscount"); 186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 18711201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void) 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 1876cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("pipe"); 187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 18791f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko set_cloexec_flag(proc_poll_pipe[i]); 188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 18841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout) 188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 1893cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("panic: short read: %d", n); 189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 19061201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig) 190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 19111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd) 191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1919bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1920bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1921bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 1925cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("fork"); 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1948cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)"); 194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 19605ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 19615ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else 19625ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 19635ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif 19649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 19809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 19979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 2014cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("lost proc"); 201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 20199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2024cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("nothing ready"); 202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 20281201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void) 202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 20309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 2031d870b3c31a0139b335a66a829169bacc74624c44John Hughes struct tcb *in_syscall = NULL; 20329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 20379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 205154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath tcp = first_used_tcb(); 205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 20649dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 20659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 20669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 20679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 2068553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 20699dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 20709dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 20719dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 20729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 20739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 20749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 2075b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if ((what = poll(&pv, 1, 1)) < 0) { 20769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 20779dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 20789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 20799dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 20819dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 20829dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 20849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 20859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 2106cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("unknown pfd: %u", pfd); 210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2108b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK 21099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 2110b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif 211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 2113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 2114b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko ioctl_result = IOCTL_WSTOP(tcp); 2115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 2116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 2117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 2119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 2120b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko ioctl_result = IOCTL_STATUS(tcp); 2121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 2122b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko ioctl_result = IOCTL_WSTOP(tcp); 2123553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */ 212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 2148553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 2153cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("PIOCWSTOP"); 215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 21572e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 21582e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 21592e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 2160b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko IOCTL(tcp->pfd, PIOCRUN, 0); 21612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 21622e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 2163553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2164553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 2170ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab curcol = tcp->curcol; 217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 2174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 2176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 2177bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 2178bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 2179bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 2180bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 2181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 2182bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 2183bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 2184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 2185553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */ 218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 2188bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 21929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 21939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 2194bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 21969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 21979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 2199cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("syscall trouble"); 220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 22059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 22069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 22079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 2210cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("syscall trouble"); 221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 2214e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 2215e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin && (qual_flags[what] & QUAL_SIGNAL)) { 221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 2218ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 2219ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 22205826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 22215826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 22225826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 22235826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 22245826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 2225ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 22265826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 22275826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 2231e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAGS_ONLY_STATS 2232e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin && (qual_flags[what] & QUAL_FAULT)) { 223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 2235ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 2238bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 2239bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 22405ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko continue; 2241553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 2243cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("odd stop %d", tcp->status.PR_WHY); 224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2246ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab /* Remember current print column before continuing. */ 2247ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = curcol; 22489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 2249553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD 2250b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) 2251553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else 2252b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) 2253553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif 2254372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab { 2255cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg_and_die("PIOCRUN"); 225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2263eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int 2264eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace() 226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 227226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko struct rusage *rup = cflag ? &ru : NULL; 227326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL 2274eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath static int wait4_options = __WALL; 227526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif 227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2278eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath while (nprocs != 0) { 2279222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko if (interrupted) 2280eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 2281eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 2282eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_SETMASK, &empty_set, NULL); 228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 228426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL 228526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, wait4_options, rup); 22865bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) { 22872f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 22882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 228926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, wait4_options, rup); 22902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 22915bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) { 22922f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 229326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, __WCLONE, rup); 229426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko if (pid < 0) { 2295cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko perror_msg("wait4(__WCLONE) failed"); 22962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 22972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 229826d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else 229926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko pid = wait4(-1, &status, 0, rup); 230026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */ 230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 230426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko#endif 230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 2306eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (interactive) 2307eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath sigprocmask(SIG_BLOCK, &blocked_set, NULL); 230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 230926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko if (pid < 0) { 2310eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath switch (wait_errno) { 2311eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case EINTR: 231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 2313eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath case ECHILD: 231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 2320eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return 0; 2321eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath default: 2322eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath errno = wait_errno; 2323eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath perror("strace: wait"); 2324eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath return -1; 232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 232710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (pid == popen_pid) { 232810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin if (WIFEXITED(status) || WIFSIGNALED(status)) 23297dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko popen_pid = 0; 233010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin continue; 233110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin } 23321d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (debug) { 23331d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16]; 23341d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef LINUX 23351d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko unsigned ev = (unsigned)status >> 16; 23361d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (ev) { 23371d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko static const char *const event_names[] = { 23381d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko [PTRACE_EVENT_CLONE] = "CLONE", 23391d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko [PTRACE_EVENT_FORK] = "FORK", 23401d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko [PTRACE_EVENT_VFORK] = "VFORK", 23411d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE", 23421d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko [PTRACE_EVENT_EXEC] = "EXEC", 23431d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko [PTRACE_EVENT_EXIT] = "EXIT", 23441d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko }; 23451d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko const char *e; 23461d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (ev < ARRAY_SIZE(event_names)) 23471d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko e = event_names[ev]; 23481d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko else { 23491d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "?? (%u)", ev); 23501d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko e = buf; 23511d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko } 23521d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko fprintf(stderr, " PTRACE_EVENT_%s", e); 23531d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko } 23541d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif 23551d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko strcpy(buf, "???"); 23561d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFSIGNALED(status)) 23571d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP 23581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFSIGNALED,%ssig=%s", 23591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko WCOREDUMP(status) ? "core," : "", 23601d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko signame(WTERMSIG(status))); 23611d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else 23621d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFSIGNALED,sig=%s", 23631d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko signame(WTERMSIG(status))); 23641d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif 23651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFEXITED(status)) 23661d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status)); 23671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFSTOPPED(status)) 23681d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status))); 23695bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED 23701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko if (WIFCONTINUED(status)) 23711d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko strcpy(buf, "WIFCONTINUED"); 23725bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif 23731d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf); 23741d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko } 237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 2378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX 237941c48227a86a176da333f713d5047240885f25ccRoland McGrath if (followfork) { 2380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This is needed to go with the CLONE_PTRACE 2381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath changes in process.c/util.c: we might see 2382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath the child's initial trap before we see the 2383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath parent return from the clone syscall. 2384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath Leave the child suspended until the parent 2385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath returns from its system call. Only then 2386e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath will we have the association of parent and 2387e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath child so that we know how to do clearbpt 2388e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath in the child. */ 2389418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko tcp = alloctcb(pid); 2390833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko tcp->flags |= TCB_ATTACHED; 2391e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (!qflag) 2392833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko fprintf(stderr, "Process %d attached\n", 2393e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath pid); 23948b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 2395e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath else 2396e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath /* This can happen if a clone call used 2397e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath CLONE_PTRACE itself. */ 2398eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif 2399e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath { 2400e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath if (WIFSTOPPED(status)) 2401e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath ptrace(PTRACE_CONT, pid, (char *) 1, 0); 2402cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko error_msg_and_die("Unknown pid: %u", pid); 2403e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath } 240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2405eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* set current output file */ 2406eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath outf = tcp->outf; 2407ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab curcol = tcp->curcol; 2408eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX 240913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko if (cflag) { 241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 241276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 241313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#endif 2414eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath 241576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 2416a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2417a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = 0x100 | WTERMSIG(status); 2418e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 241976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 242076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 242113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP 24222efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath tprintf("+++ killed by %s %s+++", 24232efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath signame(WTERMSIG(status)), 242413d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko WCOREDUMP(status) ? "(core dumped) " : ""); 242513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else 242613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko tprintf("+++ killed by %s +++", 242713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko signame(WTERMSIG(status))); 24282efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif 2429ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 243176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 243276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 243376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 2435a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin if (pid == strace_child) 2436a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin exit_code = WEXITSTATUS(status); 24370a396906981a03f93c07cb912585d0679dd50899Roland McGrath if (tcp == tcp_last) { 24387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL) 24390a396906981a03f93c07cb912585d0679dd50899Roland McGrath tprintf(" <unfinished ... exit status %d>\n", 24400a396906981a03f93c07cb912585d0679dd50899Roland McGrath WEXITSTATUS(status)); 24410a396906981a03f93c07cb912585d0679dd50899Roland McGrath tcp_last = NULL; 24420a396906981a03f93c07cb912585d0679dd50899Roland McGrath } 244319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) { 244419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko printleader(tcp); 244519cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko tprintf("+++ exited with %d +++", WEXITSTATUS(status)); 244619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko printtrailer(); 244719cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko } 244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 24573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko if (status >> 16) { 2458833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko /* Ptrace event (we ignore all of them for now) */ 2459833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko goto tracing; 2460ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao } 2461ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao 246202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* 246302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * Interestingly, the process may stop 246402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * with STOPSIG equal to some other signal 2465eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * than SIGSTOP if we happend to attach 246602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * just before the process takes a signal. 2467c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * A no-MMU vforked child won't send up a signal, 2468c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger * so skip the first (lost) execve notification. 246902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath */ 2470c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger if ((tcp->flags & TCB_STARTUP) && 2471c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger (WSTOPSIG(status) == SIGSTOP || strace_vforked)) { 247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 247802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (tcp->flags & TCB_BPTSET) { 247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 248002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * One example is a breakpoint inherited from 248102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath * parent through fork (). 248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2489ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX 249044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (ptrace_setoptions) { 249144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (debug) 249244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid); 249344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) { 249444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko if (errno != ESRCH) { 249544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko /* Should never happen, really */ 249644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko perror_msg_and_die("PTRACE_SETOPTIONS"); 24973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 24983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 24993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko } 2500ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif 250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 250276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 250376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 250475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko if (WSTOPSIG(status) != syscall_trap_sig) { 250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 2512732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 251676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2518e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin if (cflag != CFLAG_ONLY_STATS 251976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 2520c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin siginfo_t si; 2521c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) 25226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin long pc = 0; 25236b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin long psr = 0; 25247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 2525932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IPSR, &psr); 2526932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko upeek(tcp, PT_CR_IIP, &pc); 25277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 25286b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI 41 25297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 25306b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR " @ %lx" 25316b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG pc 25326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else 25336b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR "%s" 25346b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG "" 25357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 25376b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { 25386b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin tprintf("--- "); 25396b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin printsiginfo(&si, verbose(tcp)); 25406b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin tprintf(" (%s)" PC_FORMAT_STR " ---", 25416b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin strsignal(WSTOPSIG(status)), 25426b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin PC_FORMAT_ARG); 25436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin } else 25446b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin tprintf("--- %s by %s" PC_FORMAT_STR " ---", 25456b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin strsignal(WSTOPSIG(status)), 25466b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin signame(WSTOPSIG(status)), 25476b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin PC_FORMAT_ARG); 2548ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko printtrailer(); 254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 2550732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) { 255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 255376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 255576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 255602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath /* we handled the STATUS, we are permitted to interrupt now. */ 255702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath if (interrupted) 255802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath return 0; 2559eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) { 2560eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* ptrace() failed in trace_syscall() with ESRCH. 2561eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Likely a result of process disappearing mid-flight. 2562eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * Observed case: exit_group() terminating 2563eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * all processes in thread group. In this case, threads 2564eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * "disappear" in an unpredictable moment without any 2565eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath * notification to strace via wait(). 2566ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko */ 2567ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko if (tcp->flags & TCB_ATTACHED) { 2568eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (tcp_last) { 2569eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath /* Do we have dangling line "syscall(param, param"? 2570178de007d14f3ae890117b540def9cf14bcb61feDenys Vlasenko * Finish the line then. 2571eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath */ 2572eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp_last->flags |= TCB_REPRINT; 2573eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unfinished ...>"); 2574eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath printtrailer(); 2575eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath } 257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 2577ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko } else { 2578eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath ptrace(PTRACE_KILL, 2579eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp->pid, (char *) 1, SIGTERM); 258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 258276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 2585ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab /* Remember current print column before continuing. */ 2586ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab tcp->curcol = curcol; 2587732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) { 258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2595bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 259676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 259976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 2602e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab va_start(args, fmt); 2603b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath if (outf) { 2604b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath int n = vfprintf(outf, fmt, args); 2605ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab if (n < 0) { 2606ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab if (outf != stderr) 2607ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab perror(outfname == NULL 2608ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab ? "<writing to pipe>" : outfname); 2609ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab } else 2610b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath curcol += n; 2611b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath } 261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 261476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 261576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 26171201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp) 261876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 2619732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last) { 2620eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath if (tcp_last->ptrace_errno) { 2621732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko if (tcp_last->flags & TCB_INSYSCALL) { 2622e62df004ce7a649c014fc0b5af058d56bc168920Denys Vlasenko tprintf(" <unavailable>) "); 2623eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tabto(acolumn); 2624732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 2625eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf("= ? <unavailable>\n"); 2626eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tcp_last->ptrace_errno = 0; 2627732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } else if (!outfname || followfork < 2 || tcp_last == tcp) { 26287e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko tcp_last->flags |= TCB_REPRINT; 2629eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath tprintf(" <unfinished ...>\n"); 2630732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko } 263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 263276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 263376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 263676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 263876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 263976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 264076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 264176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 264276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 264676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 264876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 26691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotabto(int col) 267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 2676ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void) 267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 26819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2682ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 26839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2684ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint 2685ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size) 2686ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{ 26879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 26889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 2689553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 26909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 26919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 26929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 26939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 26949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 26959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 26969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 2697553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath 2698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko return writev(fd, iov, n); 26999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 27009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 27019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2702