blob: b739cd62182ce6fc2860e337880f69a1213e02e7 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010048#include <sys/utsname.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020052# if defined __NR_tkill
53# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# else
55 /* kill() may choose arbitrarily the target task of the process group
56 while we later wait on a that specific TID. PID process waits become
57 TID task specific waits for a process under ptrace(2). */
58# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020059# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000060# endif
61#endif
62
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000063#if defined(IA64) && defined(LINUX)
64# include <asm/ptrace_offsets.h>
65#endif
66
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000067#ifdef USE_PROCFS
68#include <poll.h>
69#endif
70
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071#ifdef SVR4
72#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000073#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000074#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000075#include <sys/uio.h>
76#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000078#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000079extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000080extern int optind;
81extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000082
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083
Roland McGrath41c48222008-07-18 00:25:10 +000084int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020085unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020086/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020087static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000088int dtime = 0, xflag = 0, qflag = 0;
89cflag_t cflag = CFLAG_NONE;
Denys Vlasenkoaa6ec412012-01-24 11:35:38 +010090static int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010091
92/* -I n */
93enum {
94 INTR_NOT_SET = 0,
95 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
96 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
97 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
98 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
99 NUM_INTR_OPTS
100};
101static int opt_intr;
102/* We play with signal mask only if this mode is active: */
103#define interactive (opt_intr == INTR_WHILE_WAIT)
104
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000105/*
106 * daemonized_tracer supports -D option.
107 * With this option, strace forks twice.
108 * Unlike normal case, with -D *grandparent* process exec's,
109 * becoming a traced process. Child exits (this prevents traced process
110 * from having children it doesn't expect to have), and grandchild
111 * attaches to grandparent similarly to strace -p PID.
112 * This allows for more transparent interaction in cases
113 * when process and its parent are communicating via signals,
114 * wait() etc. Without -D, strace process gets lodged in between,
115 * disrupting parent<->child link.
116 */
117static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100119#ifdef USE_SEIZE
120static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
121# define use_seize (post_attach_sigstop == 0)
122#else
123# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
124# define use_seize 0
125#endif
126
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000127/* Sometimes we want to print only succeeding syscalls. */
128int not_failing_only = 0;
129
Grant Edwards8a082772011-04-07 20:25:40 +0000130/* Show path associated with fd arguments */
131int show_fd_path = 0;
132
133/* are we filtering traces based on paths? */
134int tracing_paths = 0;
135
Dmitry V. Levina6809652008-11-10 17:14:58 +0000136static int exit_code = 0;
137static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200138static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700139
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000140static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200141static uid_t run_uid;
142static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200145static int acolumn = DEFAULT_ACOLUMN;
146static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000147static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200148static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100149struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100150static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200151static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200152static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200153static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100155static char *os_release; /* from uname() */
156
Denys Vlasenko4c196382012-01-04 15:11:09 +0100157static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100158static int trace(void);
159static void cleanup(void);
160static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161static sigset_t empty_set, blocked_set;
162
163#ifdef HAVE_SIG_ATOMIC_T
164static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100165#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100167#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000169#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
Andreas Schwabe5355de2009-10-27 16:56:43 +0100171static struct tcb *pfd2tcb(int pfd);
172static void reaper(int sig);
173static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000174static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175
176#ifndef HAVE_POLLABLE_PROCFS
177
Andreas Schwabe5355de2009-10-27 16:56:43 +0100178static void proc_poll_open(void);
179static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180
181struct proc_pollfd {
182 int fd;
183 int revents;
184 int pid;
185};
186
187static int poller_pid;
188static int proc_poll_pipe[2] = { -1, -1 };
189
190#endif /* !HAVE_POLLABLE_PROCFS */
191
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000192#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000193#define POLLWANT POLLWRNORM
194#else
195#define POLLWANT POLLPRI
196#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000197#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198
199static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200200usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201{
202 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100203usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
204 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
205 [-P path] [PROG [ARGS]]]\n\
206 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
207 [PROG [ARGS]]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200209-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100210-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211-f -- follow forks, -ff -- with output into separate files\n\
212-F -- attempt to follow vforks, -h -- print help message\n\
213-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100214-I interruptible\n\
215 1: no signals are blocked\n\
216 2: fatal signals are blocked while decoding syscall (default)\n\
217 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
218 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
219 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000220-q -- suppress messages about attaching, detaching, etc.\n\
221-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
222-T -- print time spent in each syscall, -V -- print version\n\
223-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
224-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000225-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000226-a column -- alignment COLUMN for printing syscall results (default %d)\n\
227-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
228 options: trace, abbrev, verbose, raw, signal, read, or write\n\
229-o file -- send trace output to FILE instead of stderr\n\
230-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
231-p pid -- trace process with process id PID, may be repeated\n\
232-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
233-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
234-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000235-E var=val -- put var=val in the environment for command\n\
236-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000237-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000238" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000239-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000240 */
241, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242 exit(exitval);
243}
244
Denys Vlasenko75422762011-05-27 14:36:01 +0200245static void die(void) __attribute__ ((noreturn));
246static void die(void)
247{
248 if (strace_tracer_pid == getpid()) {
249 cflag = 0;
250 cleanup();
251 }
252 exit(1);
253}
254
255static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200256{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100257 char *msg;
258
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000259 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100260
261 /* We want to print entire message with single fprintf to ensure
262 * message integrity if stderr is shared with other programs.
263 * Thus we use vasprintf + single fprintf.
264 */
265 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100266 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100267 if (err_no)
268 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
269 else
270 fprintf(stderr, "%s: %s\n", progname, msg);
271 free(msg);
272 } else {
273 /* malloc in vasprintf failed, try it without malloc */
274 fprintf(stderr, "%s: ", progname);
275 vfprintf(stderr, fmt, p);
276 if (err_no)
277 fprintf(stderr, ": %s\n", strerror(err_no));
278 else
279 putc('\n', stderr);
280 }
281 /* We don't switch stderr to buffered, thus fprintf(stderr)
282 * always flushes its output and this is not necessary: */
283 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200284}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200285
Denys Vlasenko75422762011-05-27 14:36:01 +0200286void error_msg(const char *fmt, ...)
287{
288 va_list p;
289 va_start(p, fmt);
290 verror_msg(0, fmt, p);
291 va_end(p);
292}
293
294void error_msg_and_die(const char *fmt, ...)
295{
296 va_list p;
297 va_start(p, fmt);
298 verror_msg(0, fmt, p);
299 die();
300}
301
302void perror_msg(const char *fmt, ...)
303{
304 va_list p;
305 va_start(p, fmt);
306 verror_msg(errno, fmt, p);
307 va_end(p);
308}
309
310void perror_msg_and_die(const char *fmt, ...)
311{
312 va_list p;
313 va_start(p, fmt);
314 verror_msg(errno, fmt, p);
315 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200316}
317
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200318void die_out_of_memory(void)
319{
320 static bool recursed = 0;
321 if (recursed)
322 exit(1);
323 recursed = 1;
324 error_msg_and_die("Out of memory");
325}
326
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000327#ifdef SVR4
328#ifdef MIPS
329void
330foobar()
331{
332}
333#endif /* MIPS */
334#endif /* SVR4 */
335
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400336/* Glue for systems without a MMU that cannot provide fork() */
337#ifdef HAVE_FORK
338# define strace_vforked 0
339#else
340# define strace_vforked 1
341# define fork() vfork()
342#endif
343
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100344#ifdef USE_SEIZE
345static int
346ptrace_attach_or_seize(int pid)
347{
348 int r;
349 if (!use_seize)
350 return ptrace(PTRACE_ATTACH, pid, 0, 0);
351 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
352 if (r)
353 return r;
354 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
355 return r;
356}
357#else
358# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
359#endif
360
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200361static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362set_cloexec_flag(int fd)
363{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200364 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000365
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200366 flags = fcntl(fd, F_GETFD);
367 if (flags < 0) {
368 /* Can happen only if fd is bad.
369 * Should never happen: if it does, we have a bug
370 * in the caller. Therefore we just abort
371 * instead of propagating the error.
372 */
373 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000374 }
375
376 newflags = flags | FD_CLOEXEC;
377 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200378 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000379
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200380 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000381}
382
383/*
384 * When strace is setuid executable, we have to swap uids
385 * before and after filesystem and process management operations.
386 */
387static void
388swap_uid(void)
389{
390#ifndef SVR4
391 int euid = geteuid(), uid = getuid();
392
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200393 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200394 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000395 }
396#endif
397}
398
Roland McGrath4bfa6262007-07-05 20:03:16 +0000399#if _LFS64_LARGEFILE
400# define fopen_for_output fopen64
401#else
402# define fopen_for_output fopen
403#endif
404
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000405static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200406strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000407{
408 FILE *fp;
409
410 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200411 fp = fopen_for_output(path, "w");
412 if (!fp)
413 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000414 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200415 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000416 return fp;
417}
418
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200419static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420
421#ifndef _PATH_BSHELL
422# define _PATH_BSHELL "/bin/sh"
423#endif
424
425/*
426 * We cannot use standard popen(3) here because we have to distinguish
427 * popen child process from other processes we trace, and standard popen(3)
428 * does not export its child's pid.
429 */
430static FILE *
431strace_popen(const char *command)
432{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200433 FILE *fp;
434 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000435
436 swap_uid();
437 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200438 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000439
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200440 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000441
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200442 popen_pid = vfork();
443 if (popen_pid == -1)
444 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000445
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200446 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000447 /* child */
448 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200449 if (fds[0] != 0) {
450 if (dup2(fds[0], 0))
451 perror_msg_and_die("dup2");
452 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000453 }
454 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200455 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000456 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200457
458 /* parent */
459 close(fds[0]);
460 swap_uid();
461 fp = fdopen(fds[1], "w");
462 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200463 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200464 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000465}
466
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200467static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000468newoutf(struct tcb *tcp)
469{
470 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000471 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000472 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200473 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000474 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000475}
476
Roland McGrath02203312007-06-11 22:06:31 +0000477static void
478startup_attach(void)
479{
480 int tcbi;
481 struct tcb *tcp;
482
483 /*
484 * Block user interruptions as we would leave the traced
485 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200486 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200487 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000488 */
489 if (interactive)
490 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
491
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000492 if (daemonized_tracer) {
493 pid_t pid = fork();
494 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200495 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000496 }
497 if (pid) { /* parent */
498 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200499 * Wait for grandchild to attach to straced process
500 * (grandparent). Grandchild SIGKILLs us after it attached.
501 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000502 * it proceeds to exec the straced program.
503 */
504 pause();
505 _exit(0); /* paranoia */
506 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200507 /* grandchild */
508 /* We will be the tracer process. Remember our new pid: */
509 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000510 }
511
Roland McGrath02203312007-06-11 22:06:31 +0000512 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
513 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200514
Denys Vlasenkod116a732011-09-05 14:01:33 +0200515 /* Is this a process we should attach to, but not yet attached? */
516 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
517 continue; /* no */
518
519 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000520 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200521 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000522
523#ifdef USE_PROCFS
524 if (proc_open(tcp, 1) < 0) {
525 fprintf(stderr, "trouble opening proc file\n");
526 droptcb(tcp);
527 continue;
528 }
529#else /* !USE_PROCFS */
530# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000531 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000532 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000533 DIR *dir;
534
535 sprintf(procdir, "/proc/%d/task", tcp->pid);
536 dir = opendir(procdir);
537 if (dir != NULL) {
538 unsigned int ntid = 0, nerr = 0;
539 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200540
Roland McGrath02203312007-06-11 22:06:31 +0000541 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200542 struct tcb *cur_tcp;
543 int tid;
544
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000545 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000546 continue;
547 tid = atoi(de->d_name);
548 if (tid <= 0)
549 continue;
550 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100551 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000552 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200553 if (debug)
554 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200555 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200556 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200557 if (debug)
558 fprintf(stderr, "attach to pid %d succeeded\n", tid);
559 cur_tcp = tcp;
560 if (tid != tcp->pid)
561 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100562 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000563 }
564 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200565 if (interactive) {
566 sigprocmask(SIG_SETMASK, &empty_set, NULL);
567 if (interrupted)
568 goto ret;
569 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
570 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000571 ntid -= nerr;
572 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000573 perror("attach: ptrace(PTRACE_ATTACH, ...)");
574 droptcb(tcp);
575 continue;
576 }
577 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000578 fprintf(stderr, ntid > 1
579? "Process %u attached with %u threads - interrupt to quit\n"
580: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200581 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000582 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200583 if (!(tcp->flags & TCB_STARTUP)) {
584 /* -p PID, we failed to attach to PID itself
585 * but did attach to some of its sibling threads.
586 * Drop PID's tcp.
587 */
588 droptcb(tcp);
589 }
Roland McGrath02203312007-06-11 22:06:31 +0000590 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000591 } /* if (opendir worked) */
592 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200593# endif /* LINUX */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100594 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000595 perror("attach: ptrace(PTRACE_ATTACH, ...)");
596 droptcb(tcp);
597 continue;
598 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100599 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200600 if (debug)
601 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000602
603 if (daemonized_tracer) {
604 /*
605 * It is our grandparent we trace, not a -p PID.
606 * Don't want to just detach on exit, so...
607 */
608 tcp->flags &= ~TCB_ATTACHED;
609 /*
610 * Make parent go away.
611 * Also makes grandparent's wait() unblock.
612 */
613 kill(getppid(), SIGKILL);
614 }
615
Roland McGrath02203312007-06-11 22:06:31 +0000616#endif /* !USE_PROCFS */
617 if (!qflag)
618 fprintf(stderr,
619 "Process %u attached - interrupt to quit\n",
620 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200621 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000622
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200623 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000624 if (interactive)
625 sigprocmask(SIG_SETMASK, &empty_set, NULL);
626}
627
628static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200629startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000630{
631 struct stat statbuf;
632 const char *filename;
633 char pathname[MAXPATHLEN];
634 int pid = 0;
635 struct tcb *tcp;
636
637 filename = argv[0];
638 if (strchr(filename, '/')) {
639 if (strlen(filename) > sizeof pathname - 1) {
640 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200641 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000642 }
643 strcpy(pathname, filename);
644 }
645#ifdef USE_DEBUGGING_EXEC
646 /*
647 * Debuggers customarily check the current directory
648 * first regardless of the path but doing that gives
649 * security geeks a panic attack.
650 */
651 else if (stat(filename, &statbuf) == 0)
652 strcpy(pathname, filename);
653#endif /* USE_DEBUGGING_EXEC */
654 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000655 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000656 int m, n, len;
657
658 for (path = getenv("PATH"); path && *path; path += m) {
659 if (strchr(path, ':')) {
660 n = strchr(path, ':') - path;
661 m = n + 1;
662 }
663 else
664 m = n = strlen(path);
665 if (n == 0) {
666 if (!getcwd(pathname, MAXPATHLEN))
667 continue;
668 len = strlen(pathname);
669 }
670 else if (n > sizeof pathname - 1)
671 continue;
672 else {
673 strncpy(pathname, path, n);
674 len = n;
675 }
676 if (len && pathname[len - 1] != '/')
677 pathname[len++] = '/';
678 strcpy(pathname + len, filename);
679 if (stat(pathname, &statbuf) == 0 &&
680 /* Accept only regular files
681 with some execute bits set.
682 XXX not perfect, might still fail */
683 S_ISREG(statbuf.st_mode) &&
684 (statbuf.st_mode & 0111))
685 break;
686 }
687 }
688 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200689 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000690 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000691 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000692 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200693 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000694 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200695 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
696 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000697 ) {
698 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200699 if (outf != stderr)
700 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000701#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200702# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000703 /* Kludge for SGI, see proc_open for details. */
704 sa.sa_handler = foobar;
705 sa.sa_flags = 0;
706 sigemptyset(&sa.sa_mask);
707 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200708# endif
709# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000710 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200711# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200712 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200713# endif
Roland McGrath02203312007-06-11 22:06:31 +0000714#else /* !USE_PROCFS */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100715 if (!daemonized_tracer && !use_seize) {
716 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200717 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000718 }
Roland McGrath02203312007-06-11 22:06:31 +0000719 }
Roland McGrath02203312007-06-11 22:06:31 +0000720
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200721 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000722 uid_t run_euid = run_uid;
723 gid_t run_egid = run_gid;
724
725 if (statbuf.st_mode & S_ISUID)
726 run_euid = statbuf.st_uid;
727 if (statbuf.st_mode & S_ISGID)
728 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000729 /*
730 * It is important to set groups before we
731 * lose privileges on setuid.
732 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200733 if (initgroups(username, run_gid) < 0) {
734 perror_msg_and_die("initgroups");
735 }
736 if (setregid(run_gid, run_egid) < 0) {
737 perror_msg_and_die("setregid");
738 }
739 if (setreuid(run_uid, run_euid) < 0) {
740 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000741 }
742 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200743 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000744 setreuid(run_uid, run_uid);
745
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000746 if (!daemonized_tracer) {
747 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200748 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200750 * the immediately following execve syscall.
751 * Can't do this on NOMMU systems, we are after
752 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000753 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400754 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200755 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000756 } else {
757 struct sigaction sv_sigchld;
758 sigaction(SIGCHLD, NULL, &sv_sigchld);
759 /*
760 * Make sure it is not SIG_IGN, otherwise wait
761 * will not block.
762 */
763 signal(SIGCHLD, SIG_DFL);
764 /*
765 * Wait for grandchild to attach to us.
766 * It kills child after that, and wait() unblocks.
767 */
768 alarm(3);
769 wait(NULL);
770 alarm(0);
771 sigaction(SIGCHLD, &sv_sigchld, NULL);
772 }
Roland McGrath02203312007-06-11 22:06:31 +0000773#endif /* !USE_PROCFS */
774
775 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200776 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000777 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000778
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200779 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200780
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200781 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100782 if (!use_seize) {
783 /* child did PTRACE_TRACEME, nothing to do in parent */
784 } else {
785 if (!strace_vforked) {
786 /* Wait until child stopped itself */
787 int status;
788 while (waitpid(pid, &status, WSTOPPED) < 0) {
789 if (errno == EINTR)
790 continue;
791 perror_msg_and_die("waitpid");
792 }
793 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
794 kill(pid, SIGKILL);
795 perror_msg_and_die("Unexpected wait status %x", status);
796 }
797 }
798 /* Else: vforked case, we have no way to sync.
799 * Just attach to it as soon as possible.
800 * This means that we may miss a few first syscalls...
801 */
802
803 if (ptrace_attach_or_seize(pid)) {
804 kill(pid, SIGKILL);
805 perror_msg_and_die("Can't attach to %d", pid);
806 }
807 if (!strace_vforked)
808 kill(pid, SIGCONT);
809 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200810 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200811 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100812 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200813 else
814 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200815 }
816 else {
817 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
818 strace_tracer_pid = getpid();
819 /* The tracee is our parent: */
820 pid = getppid();
821 tcp = alloctcb(pid);
822 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000823 tcp->flags |= TCB_ATTACHED;
824 }
Roland McGrath02203312007-06-11 22:06:31 +0000825#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000826 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200827 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000828 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200829#endif
Roland McGrath02203312007-06-11 22:06:31 +0000830}
831
Wang Chaob13c0de2010-11-12 17:25:19 +0800832#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000833static void kill_save_errno(pid_t pid, int sig)
834{
835 int saved_errno = errno;
836
837 (void) kill(pid, sig);
838 errno = saved_errno;
839}
840
Wang Chaob13c0de2010-11-12 17:25:19 +0800841/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000842 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800843 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000844 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800845 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000846static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200847test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800848{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000849 int pid, expected_grandchild = 0, found_grandchild = 0;
850 const unsigned int test_options = PTRACE_O_TRACECLONE |
851 PTRACE_O_TRACEFORK |
852 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800853
Denys Vlasenko5d645812011-08-20 12:48:18 +0200854 pid = fork();
855 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000856 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200857 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000858 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100859 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000860 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
861 __func__);
862 kill(pid, SIGSTOP);
863 if (fork() < 0)
864 perror_msg_and_die("fork");
865 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800866 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000867
868 while (1) {
869 int status, tracee_pid;
870
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000871 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000872 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000873 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000874 if (errno == EINTR)
875 continue;
876 else if (errno == ECHILD)
877 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000878 kill_save_errno(pid, SIGKILL);
879 perror_msg_and_die("%s: unexpected wait result %d",
880 __func__, tracee_pid);
881 }
882 if (WIFEXITED(status)) {
883 if (WEXITSTATUS(status)) {
884 if (tracee_pid != pid)
885 kill_save_errno(pid, SIGKILL);
886 error_msg_and_die("%s: unexpected exit status %u",
887 __func__, WEXITSTATUS(status));
888 }
889 continue;
890 }
891 if (WIFSIGNALED(status)) {
892 if (tracee_pid != pid)
893 kill_save_errno(pid, SIGKILL);
894 error_msg_and_die("%s: unexpected signal %u",
895 __func__, WTERMSIG(status));
896 }
897 if (!WIFSTOPPED(status)) {
898 if (tracee_pid != pid)
899 kill_save_errno(tracee_pid, SIGKILL);
900 kill(pid, SIGKILL);
901 error_msg_and_die("%s: unexpected wait status %x",
902 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000903 }
904 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000905 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000906 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
907 kill_save_errno(tracee_pid, SIGKILL);
908 kill_save_errno(pid, SIGKILL);
909 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800910 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000911 continue;
912 }
913 switch (WSTOPSIG(status)) {
914 case SIGSTOP:
915 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
916 && errno != EINVAL && errno != EIO)
917 perror_msg("PTRACE_SETOPTIONS");
918 break;
919 case SIGTRAP:
920 if (status >> 16 == PTRACE_EVENT_FORK) {
921 long msg = 0;
922
923 if (ptrace(PTRACE_GETEVENTMSG, pid,
924 NULL, (long) &msg) == 0)
925 expected_grandchild = msg;
926 }
927 break;
928 }
929 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
930 kill_save_errno(pid, SIGKILL);
931 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800932 }
933 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000934 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200935 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000936 if (debug)
937 fprintf(stderr, "ptrace_setoptions = %#x\n",
938 ptrace_setoptions);
939 return;
940 }
941 error_msg("Test for PTRACE_O_TRACECLONE failed, "
942 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800943}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200944
945/*
946 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
947 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
948 * and then see whether it will stop with (SIGTRAP | 0x80).
949 *
950 * Use of this option enables correct handling of user-generated SIGTRAPs,
951 * and SIGTRAPs generated by special instructions such as int3 on x86:
952 * _start: .globl _start
953 * int3
954 * movl $42, %ebx
955 * movl $1, %eax
956 * int $0x80
957 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
958 */
959static void
960test_ptrace_setoptions_for_all(void)
961{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000962 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
963 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200964 int pid;
965 int it_worked = 0;
966
967 pid = fork();
968 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200969 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200970
971 if (pid == 0) {
972 pid = getpid();
973 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200974 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000975 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
976 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200977 kill(pid, SIGSTOP);
978 _exit(0); /* parent should see entry into this syscall */
979 }
980
981 while (1) {
982 int status, tracee_pid;
983
984 errno = 0;
985 tracee_pid = wait(&status);
986 if (tracee_pid <= 0) {
987 if (errno == EINTR)
988 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000989 kill_save_errno(pid, SIGKILL);
990 perror_msg_and_die("%s: unexpected wait result %d",
991 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200992 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200993 if (WIFEXITED(status)) {
994 if (WEXITSTATUS(status) == 0)
995 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000996 error_msg_and_die("%s: unexpected exit status %u",
997 __func__, WEXITSTATUS(status));
998 }
999 if (WIFSIGNALED(status)) {
1000 error_msg_and_die("%s: unexpected signal %u",
1001 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001002 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001003 if (!WIFSTOPPED(status)) {
1004 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001005 error_msg_and_die("%s: unexpected wait status %x",
1006 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001007 }
1008 if (WSTOPSIG(status) == SIGSTOP) {
1009 /*
1010 * We don't check "options aren't accepted" error.
1011 * If it happens, we'll never get (SIGTRAP | 0x80),
1012 * and thus will decide to not use the option.
1013 * IOW: the outcome of the test will be correct.
1014 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001015 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1016 && errno != EINVAL && errno != EIO)
1017 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001018 }
1019 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1020 it_worked = 1;
1021 }
1022 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001023 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001024 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001025 }
1026 }
1027
1028 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001029 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001030 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001031 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001032 fprintf(stderr, "ptrace_setoptions = %#x\n",
1033 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001034 return;
1035 }
1036
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001037 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1038 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001039}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001040
1041# ifdef USE_SEIZE
1042static void
1043test_ptrace_seize(void)
1044{
1045 int pid;
1046
1047 pid = fork();
1048 if (pid < 0)
1049 perror_msg_and_die("fork");
1050
1051 if (pid == 0) {
1052 pause();
1053 _exit(0);
1054 }
1055
1056 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1057 * attaching tracee continues to run unless a trap condition occurs.
1058 * PTRACE_SEIZE doesn't affect signal or group stop state.
1059 */
1060 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1061 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1062 } else if (debug) {
1063 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1064 }
1065
1066 kill(pid, SIGKILL);
1067
1068 while (1) {
1069 int status, tracee_pid;
1070
1071 errno = 0;
1072 tracee_pid = waitpid(pid, &status, 0);
1073 if (tracee_pid <= 0) {
1074 if (errno == EINTR)
1075 continue;
1076 perror_msg_and_die("%s: unexpected wait result %d",
1077 __func__, tracee_pid);
1078 }
1079 if (WIFSIGNALED(status)) {
1080 return;
1081 }
1082 error_msg_and_die("%s: unexpected wait status %x",
1083 __func__, status);
1084 }
1085}
1086# else /* !USE_SEIZE */
1087# define test_ptrace_seize() ((void)0)
1088# endif
1089
Wang Chaob13c0de2010-11-12 17:25:19 +08001090#endif
1091
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001092/* Noinline: don't want main to have struct utsname permanently on stack */
1093static void __attribute__ ((noinline))
1094get_os_release(void)
1095{
1096 struct utsname u;
1097 if (uname(&u) < 0)
1098 perror_msg_and_die("uname");
1099 os_release = strdup(u.release);
1100 if (!os_release)
1101 die_out_of_memory();
1102}
1103
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001105main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 struct tcb *tcp;
1108 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001109 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 struct sigaction sa;
1111
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001112 progname = argv[0] ? argv[0] : "strace";
1113
Denys Vlasenko75422762011-05-27 14:36:01 +02001114 strace_tracer_pid = getpid();
1115
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001116 get_os_release();
1117
Roland McGrathee9d4352002-12-18 04:16:10 +00001118 /* Allocate the initial tcbtab. */
1119 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001120 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001121 if (!tcbtab)
1122 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001123 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001124 if (!tcp)
1125 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001126 for (c = 0; c < tcbtabsize; c++)
1127 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001128
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001130 set_sortby(DEFAULT_SORTBY);
1131 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 qualify("trace=all");
1133 qualify("abbrev=all");
1134 qualify("verbose=all");
1135 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001137 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001138#ifndef USE_PROCFS
1139 "D"
1140#endif
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001141 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142 switch (c) {
1143 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001144 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001145 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001146 }
1147 cflag = CFLAG_ONLY_STATS;
1148 break;
1149 case 'C':
1150 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001151 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001152 }
1153 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 break;
1155 case 'd':
1156 debug++;
1157 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001158#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001159 case 'D':
1160 daemonized_tracer = 1;
1161 break;
1162#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001163 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001164 optF = 1;
1165 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 case 'f':
1167 followfork++;
1168 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 case 'h':
1170 usage(stdout, 0);
1171 break;
1172 case 'i':
1173 iflag++;
1174 break;
1175 case 'q':
1176 qflag++;
1177 break;
1178 case 'r':
1179 rflag++;
1180 tflag++;
1181 break;
1182 case 't':
1183 tflag++;
1184 break;
1185 case 'T':
1186 dtime++;
1187 break;
1188 case 'x':
1189 xflag++;
1190 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001191 case 'y':
1192 show_fd_path = 1;
1193 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194 case 'v':
1195 qualify("abbrev=none");
1196 break;
1197 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001198 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 exit(0);
1200 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001201 case 'z':
1202 not_failing_only = 1;
1203 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 case 'a':
1205 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001206 if (acolumn < 0)
1207 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 break;
1209 case 'e':
1210 qualify(optarg);
1211 break;
1212 case 'o':
1213 outfname = strdup(optarg);
1214 break;
1215 case 'O':
1216 set_overhead(atoi(optarg));
1217 break;
1218 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001219 pid = atoi(optarg);
1220 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001221 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 break;
1223 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001224 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001225 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226 break;
1227 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001228 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 tcp->flags |= TCB_ATTACHED;
1230 pflag_seen++;
1231 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001232 case 'P':
1233 tracing_paths = 1;
1234 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001235 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001236 }
1237 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238 case 's':
1239 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001240 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001241 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001242 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 break;
1244 case 'S':
1245 set_sortby(optarg);
1246 break;
1247 case 'u':
1248 username = strdup(optarg);
1249 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001250 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001251 if (putenv(optarg) < 0)
1252 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001253 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001254 case 'I':
1255 opt_intr = atoi(optarg);
1256 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1257 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1258 }
1259 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 default:
1261 usage(stderr, 1);
1262 break;
1263 }
1264 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001265 argv += optind;
1266 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267
Denys Vlasenko102ec492011-08-25 01:27:59 +02001268 acolumn_spaces = malloc(acolumn + 1);
1269 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001270 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001271 memset(acolumn_spaces, ' ', acolumn);
1272 acolumn_spaces[acolumn] = '\0';
1273
Denys Vlasenko837399a2012-01-24 11:37:03 +01001274 /* Must have PROG [ARGS], or -p PID. Not both. */
1275 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001276 usage(stderr, 1);
1277
Wang Chaod322a4b2010-08-05 14:30:11 +08001278 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001279 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001280 }
1281
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001282 if (!followfork)
1283 followfork = optF;
1284
Roland McGrathcb9def62006-04-25 07:48:03 +00001285 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001286 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001287 }
1288
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289 /* See if they want to run as another user. */
1290 if (username != NULL) {
1291 struct passwd *pent;
1292
1293 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001294 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001296 pent = getpwnam(username);
1297 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001298 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299 }
1300 run_uid = pent->pw_uid;
1301 run_gid = pent->pw_gid;
1302 }
1303 else {
1304 run_uid = getuid();
1305 run_gid = getgid();
1306 }
1307
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001308#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001309 if (followfork)
1310 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001311 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001312 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001313#endif
1314
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315 /* Check if they want to redirect the output. */
1316 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001317 /* See if they want to pipe the output. */
1318 if (outfname[0] == '|' || outfname[0] == '!') {
1319 /*
1320 * We can't do the <outfname>.PID funny business
1321 * when using popen, so prohibit it.
1322 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001323 if (followfork > 1)
1324 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1325 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001326 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001327 else if (followfork <= 1)
1328 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329 }
1330
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001331 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001332 char *buf = malloc(BUFSIZ);
1333 if (!buf)
1334 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001336 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001337 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001338 if (!opt_intr)
1339 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001341 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001342 if (!opt_intr)
1343 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001344
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001345 /* argv[0] -pPID -oFILE Default interactive setting
1346 * yes 0 0 INTR_WHILE_WAIT
1347 * no 1 0 INTR_WHILE_WAIT
1348 * yes 0 1 INTR_NEVER
1349 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001350 */
1351
1352 /* STARTUP_CHILD must be called before the signal handlers get
1353 installed below as they are inherited into the spawned process.
1354 Also we do not need to be protected by them as during interruption
1355 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001356 if (argv[0])
1357 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359 sigemptyset(&empty_set);
1360 sigemptyset(&blocked_set);
1361 sa.sa_handler = SIG_IGN;
1362 sigemptyset(&sa.sa_mask);
1363 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001364 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1365 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1366 if (opt_intr != INTR_ANYWHERE) {
1367 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1368 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1369 /*
1370 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1371 * fatal signals are blocked while syscall stop is processed,
1372 * and acted on in between, when waiting for new syscall stops.
1373 * In non-interactive mode, signals are ignored.
1374 */
1375 if (opt_intr == INTR_WHILE_WAIT) {
1376 sigaddset(&blocked_set, SIGHUP);
1377 sigaddset(&blocked_set, SIGINT);
1378 sigaddset(&blocked_set, SIGQUIT);
1379 sigaddset(&blocked_set, SIGPIPE);
1380 sigaddset(&blocked_set, SIGTERM);
1381 sa.sa_handler = interrupt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382#ifdef SUNOS4
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001383 /* POSIX signals on sunos4.1 are a little broken. */
1384 sa.sa_flags = SA_INTERRUPT;
1385#endif
1386 }
1387 /* SIG_IGN, or set handler for these */
1388 sigaction(SIGHUP, &sa, NULL);
1389 sigaction(SIGINT, &sa, NULL);
1390 sigaction(SIGQUIT, &sa, NULL);
1391 sigaction(SIGPIPE, &sa, NULL);
1392 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001393 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001394#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395 sa.sa_handler = reaper;
1396 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001397#else
1398 /* Make sure SIGCHLD has the default action so that waitpid
1399 definitely works without losing track of children. The user
1400 should not have given us a bogus state to inherit, but he might
1401 have. Arguably we should detect SIG_IGN here and pass it on
1402 to children, but probably noone really needs that. */
1403 sa.sa_handler = SIG_DFL;
1404 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001405#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001407 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001408 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001409
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410 if (trace() < 0)
1411 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001412
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001414 fflush(NULL);
1415 if (exit_code > 0xff) {
1416 /* Child was killed by a signal, mimic that. */
1417 exit_code &= 0xff;
1418 signal(exit_code, SIG_DFL);
1419 raise(exit_code);
1420 /* Paranoia - what if this signal is not fatal?
1421 Exit with 128 + signo then. */
1422 exit_code += 128;
1423 }
1424 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425}
1426
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001427static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001428expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001429{
1430 /* Allocate some more TCBs and expand the table.
1431 We don't want to relocate the TCBs because our
1432 callers have pointers and it would be a pain.
1433 So tcbtab is a table of pointers. Since we never
1434 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001435 int i = tcbtabsize;
1436 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1437 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001438 if (!newtab || !newtcbs)
1439 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001440 tcbtabsize *= 2;
1441 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001442 while (i < tcbtabsize)
1443 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001444}
1445
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001447alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448{
1449 int i;
1450 struct tcb *tcp;
1451
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001452 if (nprocs == tcbtabsize)
1453 expand_tcbtab();
1454
Roland McGrathee9d4352002-12-18 04:16:10 +00001455 for (i = 0; i < tcbtabsize; i++) {
1456 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001458 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001460 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001462#if SUPPORTED_PERSONALITIES > 1
1463 tcp->currpers = current_personality;
1464#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001465#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001466 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001467#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001469 if (debug)
1470 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001471 if (command_options_parsed)
1472 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473 return tcp;
1474 }
1475 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001476 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477}
1478
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001479#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001481proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482{
1483 char proc[32];
1484 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001485#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001486 int i;
1487 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488 sigset_t signals;
1489 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001490#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491#ifndef HAVE_POLLABLE_PROCFS
1492 static int last_pfd;
1493#endif
1494
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001495#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001496 /* Open the process pseudo-files in /proc. */
1497 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001498 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1499 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500 perror("strace: open(\"/proc/...\", ...)");
1501 return -1;
1502 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001503 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001504 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001505 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1506 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001507 perror("strace: open(\"/proc/...\", ...)");
1508 return -1;
1509 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001510 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001511 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001512 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1513 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001514 perror("strace: open(\"/proc/...\", ...)");
1515 return -1;
1516 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001517 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001518#else
1519 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001520# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001521 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001522 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001523# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001524 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001525 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001526# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001527 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001528 perror("strace: open(\"/proc/...\", ...)");
1529 return -1;
1530 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001531 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001532#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001533#ifdef FREEBSD
1534 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001535 tcp->pfd_reg = open(proc, O_RDONLY);
1536 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001537 perror("strace: open(\"/proc/.../regs\", ...)");
1538 return -1;
1539 }
1540 if (cflag) {
1541 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001542 tcp->pfd_status = open(proc, O_RDONLY);
1543 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001544 perror("strace: open(\"/proc/.../status\", ...)");
1545 return -1;
1546 }
1547 } else
1548 tcp->pfd_status = -1;
1549#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001550 rebuild_pollv();
1551 if (!attaching) {
1552 /*
1553 * Wait for the child to pause. Because of a race
1554 * condition we have to poll for the event.
1555 */
1556 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001557 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001558 perror("strace: PIOCSTATUS");
1559 return -1;
1560 }
1561 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001562 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001563 }
1564 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001565#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001566 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001567 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001568 perror("strace: PIOCSTOP");
1569 return -1;
1570 }
Roland McGrath553a6092002-12-16 20:40:39 +00001571#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572#ifdef PIOCSET
1573 /* Set Run-on-Last-Close. */
1574 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001575 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001576 perror("PIOCSET PR_RLC");
1577 return -1;
1578 }
1579 /* Set or Reset Inherit-on-Fork. */
1580 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001581 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 perror("PIOC{SET,RESET} PR_FORK");
1583 return -1;
1584 }
1585#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001586#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1588 perror("PIOCSRLC");
1589 return -1;
1590 }
1591 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1592 perror("PIOC{S,R}FORK");
1593 return -1;
1594 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001595#else /* FREEBSD */
1596 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1597 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1598 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001599 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001600 }
1601 arg &= ~PF_LINGER;
1602 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001603 perror("PIOCSFL");
1604 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001605 }
1606#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001608#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001609 /* Enable all syscall entries we care about. */
1610 premptyset(&syscalls);
1611 for (i = 1; i < MAX_QUALS; ++i) {
1612 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001613 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001614 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001615 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001616 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001617 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001618#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001619 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001620#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001621#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001622 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001623#endif
1624#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001625 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001626#endif
1627#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001628 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001629#endif
1630 }
1631 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632 perror("PIOCSENTRY");
1633 return -1;
1634 }
John Hughes19e49982001-10-19 08:59:12 +00001635 /* Enable the syscall exits. */
1636 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637 perror("PIOSEXIT");
1638 return -1;
1639 }
John Hughes19e49982001-10-19 08:59:12 +00001640 /* Enable signals we care about. */
1641 premptyset(&signals);
1642 for (i = 1; i < MAX_QUALS; ++i) {
1643 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001644 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001645 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001646 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647 perror("PIOCSTRACE");
1648 return -1;
1649 }
John Hughes19e49982001-10-19 08:59:12 +00001650 /* Enable faults we care about */
1651 premptyset(&faults);
1652 for (i = 1; i < MAX_QUALS; ++i) {
1653 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001654 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001655 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001656 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 perror("PIOCSFAULT");
1658 return -1;
1659 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001660#else /* FREEBSD */
1661 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001662 arg = S_SIG | S_SCE | S_SCX;
1663 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001664 perror("PIOCBIS");
1665 return -1;
1666 }
1667#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 if (!attaching) {
1669#ifdef MIPS
1670 /*
1671 * The SGI PRSABORT doesn't work for pause() so
1672 * we send it a caught signal to wake it up.
1673 */
1674 kill(tcp->pid, SIGINT);
1675#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001676#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001678 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001679 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 perror("PIOCRUN");
1681 return -1;
1682 }
Roland McGrath553a6092002-12-16 20:40:39 +00001683#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001684#endif /* !MIPS*/
1685#ifdef FREEBSD
1686 /* wake up the child if it received the SIGSTOP */
1687 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001688#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689 for (;;) {
1690 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001691 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692 perror("PIOCWSTOP");
1693 return -1;
1694 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001695 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001696 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001697 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001698 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699 break;
1700 }
1701 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001702#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001703 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001704 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1705#else
1706 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1707#endif
1708 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709 perror("PIOCRUN");
1710 return -1;
1711 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001712#ifdef FREEBSD
1713 /* handle the case where we "opened" the child before
1714 it did the kill -STOP */
1715 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1716 tcp->status.PR_WHAT == SIGSTOP)
1717 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001718#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719 }
1720 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001721#ifdef FREEBSD
1722 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001723 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001724 /* We are attaching to an already running process.
1725 * Try to figure out the state of the process in syscalls,
1726 * to handle the first event well.
1727 * This is done by having a look at the "wchan" property of the
1728 * process, which tells where it is stopped (if it is). */
1729 FILE * status;
1730 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001731
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001732 sprintf(proc, "/proc/%d/status", tcp->pid);
1733 status = fopen(proc, "r");
1734 if (status &&
1735 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1736 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1737 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1738 strcmp(wchan, "stopevent")) {
1739 /* The process is asleep in the middle of a syscall.
1740 Fake the syscall entry event */
1741 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1742 tcp->status.PR_WHY = PR_SYSENTRY;
1743 trace_syscall(tcp);
1744 }
1745 if (status)
1746 fclose(status);
1747 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001748 }
1749#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750#ifndef HAVE_POLLABLE_PROCFS
1751 if (proc_poll_pipe[0] != -1)
1752 proc_poller(tcp->pfd);
1753 else if (nprocs > 1) {
1754 proc_poll_open();
1755 proc_poller(last_pfd);
1756 proc_poller(tcp->pfd);
1757 }
1758 last_pfd = tcp->pfd;
1759#endif /* !HAVE_POLLABLE_PROCFS */
1760 return 0;
1761}
1762
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001763#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001765static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001766pid2tcb(int pid)
1767{
1768 int i;
1769
1770 if (pid <= 0)
1771 return NULL;
1772
1773 for (i = 0; i < tcbtabsize; i++) {
1774 struct tcb *tcp = tcbtab[i];
1775 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1776 return tcp;
1777 }
1778
1779 return NULL;
1780}
1781
1782#ifdef USE_PROCFS
1783
1784static struct tcb *
1785first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786{
1787 int i;
1788 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001789 for (i = 0; i < tcbtabsize; i++) {
1790 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791 if (tcp->flags & TCB_INUSE)
1792 return tcp;
1793 }
1794 return NULL;
1795}
1796
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001798pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799{
1800 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801
Roland McGrathca16be82003-01-10 19:55:28 +00001802 for (i = 0; i < tcbtabsize; i++) {
1803 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 if (tcp->pfd != pfd)
1805 continue;
1806 if (tcp->flags & TCB_INUSE)
1807 return tcp;
1808 }
1809 return NULL;
1810}
1811
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001812#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813
1814void
Denys Vlasenko12014262011-05-30 14:00:14 +02001815droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816{
1817 if (tcp->pid == 0)
1818 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001819
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001821 if (debug)
1822 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001823
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001824#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825 if (tcp->pfd != -1) {
1826 close(tcp->pfd);
1827 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001828# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001829 if (tcp->pfd_reg != -1) {
1830 close(tcp->pfd_reg);
1831 tcp->pfd_reg = -1;
1832 }
1833 if (tcp->pfd_status != -1) {
1834 close(tcp->pfd_status);
1835 tcp->pfd_status = -1;
1836 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001837# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001838 tcp->flags = 0; /* rebuild_pollv needs it */
1839 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001840 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001841#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001842
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001843 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001845
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001846 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847}
1848
Roland McGrath0a463882007-07-05 18:43:16 +00001849/* detach traced process; continue with sig
1850 Never call DETACH twice on the same process as both unattached and
1851 attached-unstopped processes give the same ESRCH. For unattached process we
1852 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853
1854static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001855detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856{
1857 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001858#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001859 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001860#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861
1862 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001863 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864
1865#ifdef LINUX
1866 /*
1867 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001868 * before detaching. Arghh. We go through hoops
1869 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001871#if defined(SPARC)
1872#undef PTRACE_DETACH
1873#define PTRACE_DETACH PTRACE_SUNDETACH
1874#endif
Roland McGrath02203312007-06-11 22:06:31 +00001875 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001876 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001877 * We must catch exactly one as otherwise the detached process
1878 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001879 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001880 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001881 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001882 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001884 }
1885 else if (errno != ESRCH) {
1886 /* Shouldn't happen. */
1887 perror("detach: ptrace(PTRACE_DETACH, ...)");
1888 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001889 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001890 if (errno != ESRCH)
1891 perror("detach: checking sanity");
1892 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001893 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001894 if (errno != ESRCH)
1895 perror("detach: stopping child");
1896 }
Roland McGrath02203312007-06-11 22:06:31 +00001897 else
1898 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001899 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001900 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001901#ifdef __WALL
1902 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1903 if (errno == ECHILD) /* Already gone. */
1904 break;
1905 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001906 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001907 break;
1908 }
1909#endif /* __WALL */
1910 /* No __WALL here. */
1911 if (waitpid(tcp->pid, &status, 0) < 0) {
1912 if (errno != ECHILD) {
1913 perror("detach: waiting");
1914 break;
1915 }
1916#ifdef __WCLONE
1917 /* If no processes, try clones. */
1918 if (wait4(tcp->pid, &status, __WCLONE,
1919 NULL) < 0) {
1920 if (errno != ECHILD)
1921 perror("detach: waiting");
1922 break;
1923 }
1924#endif /* __WCLONE */
1925 }
1926#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001927 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001928#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001929 if (!WIFSTOPPED(status)) {
1930 /* Au revoir, mon ami. */
1931 break;
1932 }
1933 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001934 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001935 break;
1936 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001937 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001938 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001939 : WSTOPSIG(status));
1940 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001941 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001943 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001944#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945
1946#if defined(SUNOS4)
1947 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001948 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949#endif /* SUNOS4 */
1950
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001951 if (!qflag)
1952 fprintf(stderr, "Process %u detached\n", tcp->pid);
1953
1954 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001955
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001956 return error;
1957}
1958
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001959#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001961static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962{
1963 int pid;
1964 int status;
1965
1966 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001967 }
1968}
1969
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001970#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971
1972static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001973cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001974{
1975 int i;
1976 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001977 int fatal_sig;
1978
1979 /* 'interrupted' is a volatile object, fetch it only once */
1980 fatal_sig = interrupted;
1981 if (!fatal_sig)
1982 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983
Roland McGrathee9d4352002-12-18 04:16:10 +00001984 for (i = 0; i < tcbtabsize; i++) {
1985 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 if (!(tcp->flags & TCB_INUSE))
1987 continue;
1988 if (debug)
1989 fprintf(stderr,
1990 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001991 if (printing_tcp &&
1992 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1993 tprints(" <unfinished ...>\n");
1994 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995 }
1996 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001997 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 else {
1999 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01002000 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 }
2002 }
2003 if (cflag)
2004 call_summary(outf);
2005}
2006
2007static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002008interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002009{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01002010 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011}
2012
2013#ifndef HAVE_STRERROR
2014
Roland McGrath6d2b3492002-12-30 00:51:30 +00002015#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016extern int sys_nerr;
2017extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00002018#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019
2020const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002021strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002022{
2023 static char buf[64];
2024
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002025 if (err_no < 1 || err_no >= sys_nerr) {
2026 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002027 return buf;
2028 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002029 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002030}
2031
2032#endif /* HAVE_STERRROR */
2033
2034#ifndef HAVE_STRSIGNAL
2035
Roland McGrath8f474e02003-01-14 07:53:33 +00002036#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00002037extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00002039#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
2040extern char *_sys_siglist[];
2041#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042
2043const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002044strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045{
2046 static char buf[64];
2047
2048 if (sig < 1 || sig >= NSIG) {
2049 sprintf(buf, "Unknown signal %d", sig);
2050 return buf;
2051 }
2052#ifdef HAVE__SYS_SIGLIST
2053 return _sys_siglist[sig];
2054#else
2055 return sys_siglist[sig];
2056#endif
2057}
2058
2059#endif /* HAVE_STRSIGNAL */
2060
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002061#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062
2063static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002064rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065{
2066 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02002068 free(pollv);
2069 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02002070 if (!pollv)
2071 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00002072
Roland McGrathca16be82003-01-10 19:55:28 +00002073 for (i = j = 0; i < tcbtabsize; i++) {
2074 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002075 if (!(tcp->flags & TCB_INUSE))
2076 continue;
2077 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002078 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079 j++;
2080 }
2081 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002082 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083 }
2084}
2085
2086#ifndef HAVE_POLLABLE_PROCFS
2087
2088static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002089proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091 int i;
2092
2093 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002094 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 }
2096 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02002097 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002098 }
2099}
2100
2101static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002102proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002103{
2104 int i;
2105 int n;
2106 struct proc_pollfd pollinfo;
2107
Denys Vlasenko5d645812011-08-20 12:48:18 +02002108 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
2109 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 return n;
2111 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002112 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113 }
2114 for (i = 0; i < nprocs; i++) {
2115 if (pollv[i].fd == pollinfo.fd)
2116 pollv[i].revents = pollinfo.revents;
2117 else
2118 pollv[i].revents = 0;
2119 }
2120 poller_pid = pollinfo.pid;
2121 return 1;
2122}
2123
2124static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002125wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002126{
2127}
2128
2129static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002130proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002131{
2132 struct proc_pollfd pollinfo;
2133 struct sigaction sa;
2134 sigset_t blocked_set, empty_set;
2135 int i;
2136 int n;
2137 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138#ifdef FREEBSD
2139 struct procfs_status pfs;
2140#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141
2142 switch (fork()) {
2143 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002144 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 case 0:
2146 break;
2147 default:
2148 return;
2149 }
2150
2151 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2152 sa.sa_flags = 0;
2153 sigemptyset(&sa.sa_mask);
2154 sigaction(SIGHUP, &sa, NULL);
2155 sigaction(SIGINT, &sa, NULL);
2156 sigaction(SIGQUIT, &sa, NULL);
2157 sigaction(SIGPIPE, &sa, NULL);
2158 sigaction(SIGTERM, &sa, NULL);
2159 sa.sa_handler = wakeup_handler;
2160 sigaction(SIGUSR1, &sa, NULL);
2161 sigemptyset(&blocked_set);
2162 sigaddset(&blocked_set, SIGUSR1);
2163 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2164 sigemptyset(&empty_set);
2165
2166 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002167 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168 }
2169 n = rl.rlim_cur;
2170 for (i = 0; i < n; i++) {
2171 if (i != pfd && i != proc_poll_pipe[1])
2172 close(i);
2173 }
2174
2175 pollinfo.fd = pfd;
2176 pollinfo.pid = getpid();
2177 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002178#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002179 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2180#else
2181 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2182#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002183 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 switch (errno) {
2185 case EINTR:
2186 continue;
2187 case EBADF:
2188 pollinfo.revents = POLLERR;
2189 break;
2190 case ENOENT:
2191 pollinfo.revents = POLLHUP;
2192 break;
2193 default:
2194 perror("proc_poller: PIOCWSTOP");
2195 }
2196 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2197 _exit(0);
2198 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002199 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2201 sigsuspend(&empty_set);
2202 }
2203}
2204
2205#endif /* !HAVE_POLLABLE_PROCFS */
2206
2207static int
2208choose_pfd()
2209{
2210 int i, j;
2211 struct tcb *tcp;
2212
2213 static int last;
2214
2215 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002216 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002217 /*
2218 * The previous process is ready to run again. We'll
2219 * let it do so if it is currently in a syscall. This
2220 * heuristic improves the readability of the trace.
2221 */
2222 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002223 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224 return pollv[last].fd;
2225 }
2226
2227 for (i = 0; i < nprocs; i++) {
2228 /* Let competing children run round robin. */
2229 j = (i + last + 1) % nprocs;
2230 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2231 tcp = pfd2tcb(pollv[j].fd);
2232 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002233 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 }
2235 droptcb(tcp);
2236 return -1;
2237 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002238 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002239 last = j;
2240 return pollv[j].fd;
2241 }
2242 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002243 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244}
2245
2246static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002247trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002249#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002250 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002251#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002252 struct tcb *tcp;
2253 int pfd;
2254 int what;
2255 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002256 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257
2258 for (;;) {
2259 if (interactive)
2260 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2261
2262 if (nprocs == 0)
2263 break;
2264
2265 switch (nprocs) {
2266 case 1:
2267#ifndef HAVE_POLLABLE_PROCFS
2268 if (proc_poll_pipe[0] == -1) {
2269#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002270 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002271 if (!tcp)
2272 continue;
2273 pfd = tcp->pfd;
2274 if (pfd == -1)
2275 continue;
2276 break;
2277#ifndef HAVE_POLLABLE_PROCFS
2278 }
2279 /* fall through ... */
2280#endif /* !HAVE_POLLABLE_PROCFS */
2281 default:
2282#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002283#ifdef POLL_HACK
2284 /* On some systems (e.g. UnixWare) we get too much ugly
2285 "unfinished..." stuff when multiple proceses are in
2286 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002287
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002288 if (in_syscall) {
2289 struct pollfd pv;
2290 tcp = in_syscall;
2291 in_syscall = NULL;
2292 pv.fd = tcp->pfd;
2293 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002294 what = poll(&pv, 1, 1);
2295 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002296 if (interrupted)
2297 return 0;
2298 continue;
2299 }
2300 else if (what == 1 && pv.revents & POLLWANT) {
2301 goto FOUND;
2302 }
2303 }
2304#endif
2305
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306 if (poll(pollv, nprocs, INFTIM) < 0) {
2307 if (interrupted)
2308 return 0;
2309 continue;
2310 }
2311#else /* !HAVE_POLLABLE_PROCFS */
2312 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2313 if (interrupted)
2314 return 0;
2315 continue;
2316 }
2317#endif /* !HAVE_POLLABLE_PROCFS */
2318 pfd = choose_pfd();
2319 if (pfd == -1)
2320 continue;
2321 break;
2322 }
2323
2324 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002325 tcp = pfd2tcb(pfd);
2326 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002327 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002328 }
John Hughesb6643082002-05-23 11:02:22 +00002329#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002330 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002331#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002332 /* Get the status of the process. */
2333 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002334#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002335 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002336#else /* FREEBSD */
2337 /* Thanks to some scheduling mystery, the first poller
2338 sometimes waits for the already processed end of fork
2339 event. Doing a non blocking poll here solves the problem. */
2340 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002341 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002342 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002343 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002344#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 ioctl_errno = errno;
2346#ifndef HAVE_POLLABLE_PROCFS
2347 if (proc_poll_pipe[0] != -1) {
2348 if (ioctl_result < 0)
2349 kill(poller_pid, SIGKILL);
2350 else
2351 kill(poller_pid, SIGUSR1);
2352 }
2353#endif /* !HAVE_POLLABLE_PROCFS */
2354 }
2355 if (interrupted)
2356 return 0;
2357
2358 if (interactive)
2359 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2360
2361 if (ioctl_result < 0) {
2362 /* Find out what happened if it failed. */
2363 switch (ioctl_errno) {
2364 case EINTR:
2365 case EBADF:
2366 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002367#ifdef FREEBSD
2368 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002369#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002370 case ENOENT:
2371 droptcb(tcp);
2372 continue;
2373 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002374 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002375 }
2376 }
2377
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002378#ifdef FREEBSD
2379 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2380 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002381 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002382 continue;
2383 }
Roland McGrath553a6092002-12-16 20:40:39 +00002384#endif
2385
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 /* clear the just started flag */
2387 tcp->flags &= ~TCB_STARTUP;
2388
2389 /* set current output file */
2390 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002391 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002392
2393 if (cflag) {
2394 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002395#ifdef FREEBSD
2396 char buf[1024];
2397 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398
Denys Vlasenko5d645812011-08-20 12:48:18 +02002399 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2400 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002401 buf[len] = '\0';
2402 sscanf(buf,
2403 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2404 &stime.tv_sec, &stime.tv_usec);
2405 } else
2406 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002407#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002408 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2409 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002410#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2412 tcp->stime = stime;
2413 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002414 what = tcp->status.PR_WHAT;
2415 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002416#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002417 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002418 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2419 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002421 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002422 }
2423 }
2424 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002425#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002426 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002427#ifdef POLL_HACK
2428 in_syscall = tcp;
2429#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 case PR_SYSEXIT:
2431 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002432 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002433 }
2434 break;
2435 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002436 if (cflag != CFLAG_ONLY_STATS
2437 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002438 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002439 tprintf("--- %s (%s) ---\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002440 signame(what), strsignal(what));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002441 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002442#ifdef PR_INFO
2443 if (tcp->status.PR_INFO.si_signo == what) {
2444 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002445 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002446 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002447 tprints("\n");
2448 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002449 }
2450#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002451 }
2452 break;
2453 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002454 if (cflag != CFLAGS_ONLY_STATS
2455 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002457 tprintf("=== FAULT %d ===\n", what);
2458 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002459 }
2460 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002461#ifdef FREEBSD
2462 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002463 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002464#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002465 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002466 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002467 break;
2468 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002469 /* Remember current print column before continuing. */
2470 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002471 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002472#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002473 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002474#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002475 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002476#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002477 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002478 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479 }
2480 }
2481 return 0;
2482}
2483
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002484#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002485
Roland McGratheb9e2e82009-06-02 16:49:22 -07002486static int
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002487trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002489#ifdef LINUX
2490 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002491 struct rusage *rup = cflag ? &ru : NULL;
2492# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002493 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002494# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495#endif /* LINUX */
2496
Roland McGratheb9e2e82009-06-02 16:49:22 -07002497 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002498 int pid;
2499 int wait_errno;
2500 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002501 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002502 struct tcb *tcp;
2503 unsigned event;
2504
Denys Vlasenko222713a2009-03-17 14:29:59 +00002505 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002506 return 0;
2507 if (interactive)
2508 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002509#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002510# ifdef __WALL
2511 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002512 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002513 /* this kernel does not support __WALL */
2514 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002515 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002516 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002517 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002518 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002519 pid = wait4(-1, &status, __WCLONE, rup);
2520 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002521 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002522 }
2523 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002524# else
2525 pid = wait4(-1, &status, 0, rup);
2526# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002527#endif /* LINUX */
2528#ifdef SUNOS4
2529 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002530#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002531 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002532 if (interactive)
2533 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002535 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002536 switch (wait_errno) {
2537 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002538 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002539 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 /*
2541 * We would like to verify this case
2542 * but sometimes a race in Solbourne's
2543 * version of SunOS sometimes reports
2544 * ECHILD before sending us SIGCHILD.
2545 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002546 return 0;
2547 default:
2548 errno = wait_errno;
2549 perror("strace: wait");
2550 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 }
2552 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002553 if (pid == popen_pid) {
2554 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002555 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002556 continue;
2557 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002558
2559 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002560 if (debug) {
2561 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2562#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002563 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002564 static const char *const event_names[] = {
2565 [PTRACE_EVENT_CLONE] = "CLONE",
2566 [PTRACE_EVENT_FORK] = "FORK",
2567 [PTRACE_EVENT_VFORK] = "VFORK",
2568 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2569 [PTRACE_EVENT_EXEC] = "EXEC",
2570 [PTRACE_EVENT_EXIT] = "EXIT",
2571 };
2572 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002573 if (event < ARRAY_SIZE(event_names))
2574 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002575 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002576 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002577 e = buf;
2578 }
2579 fprintf(stderr, " PTRACE_EVENT_%s", e);
2580 }
2581#endif
2582 strcpy(buf, "???");
2583 if (WIFSIGNALED(status))
2584#ifdef WCOREDUMP
2585 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2586 WCOREDUMP(status) ? "core," : "",
2587 signame(WTERMSIG(status)));
2588#else
2589 sprintf(buf, "WIFSIGNALED,sig=%s",
2590 signame(WTERMSIG(status)));
2591#endif
2592 if (WIFEXITED(status))
2593 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2594 if (WIFSTOPPED(status))
2595 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002596#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002597 if (WIFCONTINUED(status))
2598 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002599#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002600 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2601 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002602
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002603 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002604 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002605
2606#ifdef LINUX
2607 /* Under Linux, execve changes pid to thread leader's pid,
2608 * and we see this changed pid on EVENT_EXEC and later,
2609 * execve sysexit. Leader "disappears" without exit
2610 * notification. Let user know that, drop leader's tcb,
2611 * and fix up pid in execve thread's tcb.
2612 * Effectively, execve thread's tcb replaces leader's tcb.
2613 *
2614 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2615 * on exit syscall) in multithreaded programs exactly
2616 * in order to handle this case.
2617 *
2618 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2619 * On 2.6 and earlier, it can return garbage.
2620 */
2621 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2622 long old_pid = 0;
2623 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2624 && old_pid > 0
2625 && old_pid != pid
2626 ) {
2627 struct tcb *execve_thread = pid2tcb(old_pid);
2628 if (tcp) {
2629 outf = tcp->outf;
2630 curcol = tcp->curcol;
2631 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002632 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002633 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002634 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002635 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2636 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002637 fflush(outf);
2638 }
2639 if (execve_thread) {
2640 /* swap output FILEs (needed for -ff) */
2641 tcp->outf = execve_thread->outf;
2642 execve_thread->outf = outf;
2643 }
2644 droptcb(tcp);
2645 }
2646 tcp = execve_thread;
2647 if (tcp) {
2648 tcp->pid = pid;
2649 tcp->flags |= TCB_REPRINT;
2650 }
2651 }
2652 }
2653#endif
2654
Denys Vlasenko5d645812011-08-20 12:48:18 +02002655 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002656#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002657 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002658 /* This is needed to go with the CLONE_PTRACE
2659 changes in process.c/util.c: we might see
2660 the child's initial trap before we see the
2661 parent return from the clone syscall.
2662 Leave the child suspended until the parent
2663 returns from its system call. Only then
2664 will we have the association of parent and
2665 child so that we know how to do clearbpt
2666 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002667 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002668 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002669 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002670 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002671 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002672 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002673 else
2674 /* This can happen if a clone call used
2675 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002676#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002677 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002678 if (WIFSTOPPED(status))
2679 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002680 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002681 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002682 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002683 /* set current output file */
2684 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002685 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002686#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002687 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002688 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2689 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002690 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002691#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002692
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002693 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002694 if (pid == strace_child)
2695 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002696 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002697 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2698 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002699#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002700 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002701 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002702 WCOREDUMP(status) ? "(core dumped) " : "");
2703#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002704 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002705 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002706#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01002707 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002708 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002709 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002710 droptcb(tcp);
2711 continue;
2712 }
2713 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002714 if (pid == strace_child)
2715 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002716 if (tcp == printing_tcp) {
2717 tprints(" <unfinished ...>\n");
2718 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00002719 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002720 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2721 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002722 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2723 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002724 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002725 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002726 droptcb(tcp);
2727 continue;
2728 }
2729 if (!WIFSTOPPED(status)) {
2730 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2731 droptcb(tcp);
2732 continue;
2733 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002734
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002735 /* Is this the very first time we see this tracee stopped? */
2736 if (tcp->flags & TCB_STARTUP) {
2737 if (debug)
2738 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002739 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002740 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002741 /*
2742 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002743 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002744 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002745 if (clearbpt(tcp) < 0) {
2746 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002747 droptcb(tcp);
2748 cleanup();
2749 return -1;
2750 }
2751 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002752#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002753 if (ptrace_setoptions) {
2754 if (debug)
2755 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2756 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2757 if (errno != ESRCH) {
2758 /* Should never happen, really */
2759 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002760 }
2761 }
2762 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002763#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002764 }
2765
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002766 sig = WSTOPSIG(status);
2767
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002768 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002769 /* Ptrace event */
2770#ifdef USE_SEIZE
2771 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002772 /*
2773 * PTRACE_INTERRUPT-stop or group-stop.
2774 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2775 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002776 if (sig == SIGSTOP
2777 || sig == SIGTSTP
2778 || sig == SIGTTIN
2779 || sig == SIGTTOU
2780 ) {
2781 stopped = 1;
2782 goto show_stopsig;
2783 }
2784 }
2785#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002786 goto restart_tracee_with_sig_0;
2787 }
2788
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002789 /* Is this post-attach SIGSTOP?
2790 * Interestingly, the process may stop
2791 * with STOPSIG equal to some other signal
2792 * than SIGSTOP if we happend to attach
2793 * just before the process takes a signal.
2794 */
2795 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2796 if (debug)
2797 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2798 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002799 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002800 }
2801
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002802 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002803 siginfo_t si;
2804
2805 /* Nonzero (true) if tracee is stopped by signal
2806 * (as opposed to "tracee received signal").
2807 */
2808 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002809#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002810 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002811#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002812 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002813 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002814#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002815 long pc = 0;
2816 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002817
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002818 upeek(tcp, PT_CR_IPSR, &psr);
2819 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002820
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002821# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002822 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002823# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002824# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002825#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002826# define PC_FORMAT_STR ""
2827# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002828#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002829 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002830 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002831 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002832 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002833 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002834 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002835 PC_FORMAT_ARG);
2836 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002837 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002838 strsignal(sig),
2839 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002840 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002841 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002842 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002843 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002844
2845 if (!stopped)
2846 /* It's signal-delivery-stop. Inject the signal */
2847 goto restart_tracee;
2848
2849 /* It's group-stop */
2850#ifdef USE_SEIZE
2851 if (use_seize) {
2852 /*
2853 * This ends ptrace-stop, but does *not* end group-stop.
2854 * This makes stopping signals work properly on straced process
2855 * (that is, process really stops. It used to continue to run).
2856 */
2857 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2858 cleanup();
2859 return -1;
2860 }
2861 continue;
2862 }
2863 /* We don't have PTRACE_LISTEN support... */
2864#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002865 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002866 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002867
2868 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002869 if (interrupted)
2870 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002871
2872 /* This should be syscall entry or exit.
2873 * (Or it still can be that pesky post-execve SIGTRAP!)
2874 * Handle it.
2875 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002876 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2877 /* ptrace() failed in trace_syscall() with ESRCH.
2878 * Likely a result of process disappearing mid-flight.
2879 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002880 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002881 */
2882 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002883 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002884 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002885 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002886 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002887 printing_tcp->flags |= TCB_REPRINT;
2888 tprints(" <unfinished ...>\n");
2889 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002890 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002891 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002892 /* We assume that ptrace error was caused by process death.
2893 * We used to detach(tcp) here, but since we no longer
2894 * implement "detach before death" policy/hack,
2895 * we can let this process to report its death to us
2896 * normally, via WIFEXITED or WIFSIGNALED wait status.
2897 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002898 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002899 /* It's our real child (and we also trace it) */
2900 /* my_tkill(pid, SIGKILL); - why? */
2901 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002902 }
2903 continue;
2904 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002905 restart_tracee_with_sig_0:
2906 sig = 0;
2907 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002908 /* Remember current print column before continuing. */
2909 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002910 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002911 cleanup();
2912 return -1;
2913 }
2914 }
2915 return 0;
2916}
2917
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002918#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002919
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002920void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002921tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002922{
2923 va_list args;
2924
Andreas Schwabe5355de2009-10-27 16:56:43 +01002925 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002926 if (outf) {
2927 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002928 if (n < 0) {
2929 if (outf != stderr)
2930 perror(outfname == NULL
2931 ? "<writing to pipe>" : outfname);
2932 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002933 curcol += n;
2934 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002935 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002936}
2937
2938void
2939tprints(const char *str)
2940{
2941 if (outf) {
2942 int n = fputs(str, outf);
2943 if (n >= 0) {
2944 curcol += strlen(str);
2945 return;
2946 }
2947 if (outf != stderr)
2948 perror(outfname == NULL
2949 ? "<writing to pipe>" : outfname);
2950 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002951}
2952
2953void
Denys Vlasenko12014262011-05-30 14:00:14 +02002954printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002955{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002956 if (printing_tcp) {
2957 if (printing_tcp->ptrace_errno) {
2958 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002959 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002960 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002961 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002962 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002963 printing_tcp->ptrace_errno = 0;
2964 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2965 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002966 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002967 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002968 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002969
2970 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002971 curcol = 0;
2972 if ((followfork == 1 || pflag_seen > 1) && outfname)
2973 tprintf("%-5d ", tcp->pid);
2974 else if (nprocs > 1 && !outfname)
2975 tprintf("[pid %5u] ", tcp->pid);
2976 if (tflag) {
2977 char str[sizeof("HH:MM:SS")];
2978 struct timeval tv, dtv;
2979 static struct timeval otv;
2980
2981 gettimeofday(&tv, NULL);
2982 if (rflag) {
2983 if (otv.tv_sec == 0)
2984 otv = tv;
2985 tv_sub(&dtv, &tv, &otv);
2986 tprintf("%6ld.%06ld ",
2987 (long) dtv.tv_sec, (long) dtv.tv_usec);
2988 otv = tv;
2989 }
2990 else if (tflag > 2) {
2991 tprintf("%ld.%06ld ",
2992 (long) tv.tv_sec, (long) tv.tv_usec);
2993 }
2994 else {
2995 time_t local = tv.tv_sec;
2996 strftime(str, sizeof(str), "%T", localtime(&local));
2997 if (tflag > 1)
2998 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2999 else
3000 tprintf("%s ", str);
3001 }
3002 }
3003 if (iflag)
3004 printcall(tcp);
3005}
3006
3007void
Denys Vlasenko102ec492011-08-25 01:27:59 +02003008tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003009{
Denys Vlasenko102ec492011-08-25 01:27:59 +02003010 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02003011 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003012}
3013
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00003014#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003015
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003016int
3017mp_ioctl(int fd, int cmd, void *arg, int size)
3018{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003019 struct iovec iov[2];
3020 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00003021
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003022 iov[0].iov_base = &cmd;
3023 iov[0].iov_len = sizeof cmd;
3024 if (arg) {
3025 ++n;
3026 iov[1].iov_base = arg;
3027 iov[1].iov_len = size;
3028 }
Roland McGrath553a6092002-12-16 20:40:39 +00003029
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003030 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003031}
3032
3033#endif