blob: 38c8518aa1c70e5a9d7f4adad1062d3c4e69766e [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) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100659 const char *colon = strchr(path, ':');
660 if (colon) {
661 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000662 m = n + 1;
663 }
664 else
665 m = n = strlen(path);
666 if (n == 0) {
667 if (!getcwd(pathname, MAXPATHLEN))
668 continue;
669 len = strlen(pathname);
670 }
671 else if (n > sizeof pathname - 1)
672 continue;
673 else {
674 strncpy(pathname, path, n);
675 len = n;
676 }
677 if (len && pathname[len - 1] != '/')
678 pathname[len++] = '/';
679 strcpy(pathname + len, filename);
680 if (stat(pathname, &statbuf) == 0 &&
681 /* Accept only regular files
682 with some execute bits set.
683 XXX not perfect, might still fail */
684 S_ISREG(statbuf.st_mode) &&
685 (statbuf.st_mode & 0111))
686 break;
687 }
688 }
689 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200690 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000691 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000692 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000693 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200694 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000695 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200696 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
697 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000698 ) {
699 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200700 if (outf != stderr)
701 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000702#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200703# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000704 /* Kludge for SGI, see proc_open for details. */
705 sa.sa_handler = foobar;
706 sa.sa_flags = 0;
707 sigemptyset(&sa.sa_mask);
708 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200709# endif
710# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000711 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200712# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200713 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200714# endif
Roland McGrath02203312007-06-11 22:06:31 +0000715#else /* !USE_PROCFS */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100716 if (!daemonized_tracer && !use_seize) {
717 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200718 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 }
Roland McGrath02203312007-06-11 22:06:31 +0000720 }
Roland McGrath02203312007-06-11 22:06:31 +0000721
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200722 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000723 uid_t run_euid = run_uid;
724 gid_t run_egid = run_gid;
725
726 if (statbuf.st_mode & S_ISUID)
727 run_euid = statbuf.st_uid;
728 if (statbuf.st_mode & S_ISGID)
729 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000730 /*
731 * It is important to set groups before we
732 * lose privileges on setuid.
733 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200734 if (initgroups(username, run_gid) < 0) {
735 perror_msg_and_die("initgroups");
736 }
737 if (setregid(run_gid, run_egid) < 0) {
738 perror_msg_and_die("setregid");
739 }
740 if (setreuid(run_uid, run_euid) < 0) {
741 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000742 }
743 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200744 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000745 setreuid(run_uid, run_uid);
746
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000747 if (!daemonized_tracer) {
748 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200749 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000750 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200751 * the immediately following execve syscall.
752 * Can't do this on NOMMU systems, we are after
753 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000754 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400755 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200756 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000757 } else {
758 struct sigaction sv_sigchld;
759 sigaction(SIGCHLD, NULL, &sv_sigchld);
760 /*
761 * Make sure it is not SIG_IGN, otherwise wait
762 * will not block.
763 */
764 signal(SIGCHLD, SIG_DFL);
765 /*
766 * Wait for grandchild to attach to us.
767 * It kills child after that, and wait() unblocks.
768 */
769 alarm(3);
770 wait(NULL);
771 alarm(0);
772 sigaction(SIGCHLD, &sv_sigchld, NULL);
773 }
Roland McGrath02203312007-06-11 22:06:31 +0000774#endif /* !USE_PROCFS */
775
776 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200777 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000778 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000779
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200780 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200781
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200782 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100783 if (!use_seize) {
784 /* child did PTRACE_TRACEME, nothing to do in parent */
785 } else {
786 if (!strace_vforked) {
787 /* Wait until child stopped itself */
788 int status;
789 while (waitpid(pid, &status, WSTOPPED) < 0) {
790 if (errno == EINTR)
791 continue;
792 perror_msg_and_die("waitpid");
793 }
794 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
795 kill(pid, SIGKILL);
796 perror_msg_and_die("Unexpected wait status %x", status);
797 }
798 }
799 /* Else: vforked case, we have no way to sync.
800 * Just attach to it as soon as possible.
801 * This means that we may miss a few first syscalls...
802 */
803
804 if (ptrace_attach_or_seize(pid)) {
805 kill(pid, SIGKILL);
806 perror_msg_and_die("Can't attach to %d", pid);
807 }
808 if (!strace_vforked)
809 kill(pid, SIGCONT);
810 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200811 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200812 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100813 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200814 else
815 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200816 }
817 else {
818 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
819 strace_tracer_pid = getpid();
820 /* The tracee is our parent: */
821 pid = getppid();
822 tcp = alloctcb(pid);
823 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000824 tcp->flags |= TCB_ATTACHED;
825 }
Roland McGrath02203312007-06-11 22:06:31 +0000826#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000827 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200828 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000829 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200830#endif
Roland McGrath02203312007-06-11 22:06:31 +0000831}
832
Wang Chaob13c0de2010-11-12 17:25:19 +0800833#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000834static void kill_save_errno(pid_t pid, int sig)
835{
836 int saved_errno = errno;
837
838 (void) kill(pid, sig);
839 errno = saved_errno;
840}
841
Wang Chaob13c0de2010-11-12 17:25:19 +0800842/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000843 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800844 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000845 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800846 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000847static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200848test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800849{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000850 int pid, expected_grandchild = 0, found_grandchild = 0;
851 const unsigned int test_options = PTRACE_O_TRACECLONE |
852 PTRACE_O_TRACEFORK |
853 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800854
Denys Vlasenko5d645812011-08-20 12:48:18 +0200855 pid = fork();
856 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000857 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200858 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000859 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100860 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000861 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
862 __func__);
863 kill(pid, SIGSTOP);
864 if (fork() < 0)
865 perror_msg_and_die("fork");
866 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800867 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000868
869 while (1) {
870 int status, tracee_pid;
871
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000872 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000873 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000874 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000875 if (errno == EINTR)
876 continue;
877 else if (errno == ECHILD)
878 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000879 kill_save_errno(pid, SIGKILL);
880 perror_msg_and_die("%s: unexpected wait result %d",
881 __func__, tracee_pid);
882 }
883 if (WIFEXITED(status)) {
884 if (WEXITSTATUS(status)) {
885 if (tracee_pid != pid)
886 kill_save_errno(pid, SIGKILL);
887 error_msg_and_die("%s: unexpected exit status %u",
888 __func__, WEXITSTATUS(status));
889 }
890 continue;
891 }
892 if (WIFSIGNALED(status)) {
893 if (tracee_pid != pid)
894 kill_save_errno(pid, SIGKILL);
895 error_msg_and_die("%s: unexpected signal %u",
896 __func__, WTERMSIG(status));
897 }
898 if (!WIFSTOPPED(status)) {
899 if (tracee_pid != pid)
900 kill_save_errno(tracee_pid, SIGKILL);
901 kill(pid, SIGKILL);
902 error_msg_and_die("%s: unexpected wait status %x",
903 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000904 }
905 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000906 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000907 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
908 kill_save_errno(tracee_pid, SIGKILL);
909 kill_save_errno(pid, SIGKILL);
910 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800911 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000912 continue;
913 }
914 switch (WSTOPSIG(status)) {
915 case SIGSTOP:
916 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
917 && errno != EINVAL && errno != EIO)
918 perror_msg("PTRACE_SETOPTIONS");
919 break;
920 case SIGTRAP:
921 if (status >> 16 == PTRACE_EVENT_FORK) {
922 long msg = 0;
923
924 if (ptrace(PTRACE_GETEVENTMSG, pid,
925 NULL, (long) &msg) == 0)
926 expected_grandchild = msg;
927 }
928 break;
929 }
930 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
931 kill_save_errno(pid, SIGKILL);
932 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800933 }
934 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000935 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200936 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000937 if (debug)
938 fprintf(stderr, "ptrace_setoptions = %#x\n",
939 ptrace_setoptions);
940 return;
941 }
942 error_msg("Test for PTRACE_O_TRACECLONE failed, "
943 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800944}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200945
946/*
947 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
948 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
949 * and then see whether it will stop with (SIGTRAP | 0x80).
950 *
951 * Use of this option enables correct handling of user-generated SIGTRAPs,
952 * and SIGTRAPs generated by special instructions such as int3 on x86:
953 * _start: .globl _start
954 * int3
955 * movl $42, %ebx
956 * movl $1, %eax
957 * int $0x80
958 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
959 */
960static void
961test_ptrace_setoptions_for_all(void)
962{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000963 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
964 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200965 int pid;
966 int it_worked = 0;
967
968 pid = fork();
969 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200970 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200971
972 if (pid == 0) {
973 pid = getpid();
974 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200975 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000976 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
977 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200978 kill(pid, SIGSTOP);
979 _exit(0); /* parent should see entry into this syscall */
980 }
981
982 while (1) {
983 int status, tracee_pid;
984
985 errno = 0;
986 tracee_pid = wait(&status);
987 if (tracee_pid <= 0) {
988 if (errno == EINTR)
989 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000990 kill_save_errno(pid, SIGKILL);
991 perror_msg_and_die("%s: unexpected wait result %d",
992 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200993 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200994 if (WIFEXITED(status)) {
995 if (WEXITSTATUS(status) == 0)
996 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000997 error_msg_and_die("%s: unexpected exit status %u",
998 __func__, WEXITSTATUS(status));
999 }
1000 if (WIFSIGNALED(status)) {
1001 error_msg_and_die("%s: unexpected signal %u",
1002 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001003 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001004 if (!WIFSTOPPED(status)) {
1005 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001006 error_msg_and_die("%s: unexpected wait status %x",
1007 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001008 }
1009 if (WSTOPSIG(status) == SIGSTOP) {
1010 /*
1011 * We don't check "options aren't accepted" error.
1012 * If it happens, we'll never get (SIGTRAP | 0x80),
1013 * and thus will decide to not use the option.
1014 * IOW: the outcome of the test will be correct.
1015 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001016 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1017 && errno != EINVAL && errno != EIO)
1018 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001019 }
1020 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1021 it_worked = 1;
1022 }
1023 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001024 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001025 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001026 }
1027 }
1028
1029 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001030 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001031 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001032 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001033 fprintf(stderr, "ptrace_setoptions = %#x\n",
1034 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001035 return;
1036 }
1037
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001038 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1039 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001040}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001041
1042# ifdef USE_SEIZE
1043static void
1044test_ptrace_seize(void)
1045{
1046 int pid;
1047
1048 pid = fork();
1049 if (pid < 0)
1050 perror_msg_and_die("fork");
1051
1052 if (pid == 0) {
1053 pause();
1054 _exit(0);
1055 }
1056
1057 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1058 * attaching tracee continues to run unless a trap condition occurs.
1059 * PTRACE_SEIZE doesn't affect signal or group stop state.
1060 */
1061 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1062 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1063 } else if (debug) {
1064 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1065 }
1066
1067 kill(pid, SIGKILL);
1068
1069 while (1) {
1070 int status, tracee_pid;
1071
1072 errno = 0;
1073 tracee_pid = waitpid(pid, &status, 0);
1074 if (tracee_pid <= 0) {
1075 if (errno == EINTR)
1076 continue;
1077 perror_msg_and_die("%s: unexpected wait result %d",
1078 __func__, tracee_pid);
1079 }
1080 if (WIFSIGNALED(status)) {
1081 return;
1082 }
1083 error_msg_and_die("%s: unexpected wait status %x",
1084 __func__, status);
1085 }
1086}
1087# else /* !USE_SEIZE */
1088# define test_ptrace_seize() ((void)0)
1089# endif
1090
Wang Chaob13c0de2010-11-12 17:25:19 +08001091#endif
1092
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001093/* Noinline: don't want main to have struct utsname permanently on stack */
1094static void __attribute__ ((noinline))
1095get_os_release(void)
1096{
1097 struct utsname u;
1098 if (uname(&u) < 0)
1099 perror_msg_and_die("uname");
1100 os_release = strdup(u.release);
1101 if (!os_release)
1102 die_out_of_memory();
1103}
1104
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001106main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 struct tcb *tcp;
1109 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001110 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111 struct sigaction sa;
1112
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001113 progname = argv[0] ? argv[0] : "strace";
1114
Denys Vlasenko75422762011-05-27 14:36:01 +02001115 strace_tracer_pid = getpid();
1116
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001117 get_os_release();
1118
Roland McGrathee9d4352002-12-18 04:16:10 +00001119 /* Allocate the initial tcbtab. */
1120 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001121 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001122 if (!tcbtab)
1123 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001124 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001125 if (!tcp)
1126 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001127 for (c = 0; c < tcbtabsize; c++)
1128 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001129
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001131 set_sortby(DEFAULT_SORTBY);
1132 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 qualify("trace=all");
1134 qualify("abbrev=all");
1135 qualify("verbose=all");
1136 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001138 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001139#ifndef USE_PROCFS
1140 "D"
1141#endif
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001142 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 switch (c) {
1144 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001145 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001146 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001147 }
1148 cflag = CFLAG_ONLY_STATS;
1149 break;
1150 case 'C':
1151 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001152 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001153 }
1154 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 break;
1156 case 'd':
1157 debug++;
1158 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001159#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001160 case 'D':
1161 daemonized_tracer = 1;
1162 break;
1163#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001164 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001165 optF = 1;
1166 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 case 'f':
1168 followfork++;
1169 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 case 'h':
1171 usage(stdout, 0);
1172 break;
1173 case 'i':
1174 iflag++;
1175 break;
1176 case 'q':
1177 qflag++;
1178 break;
1179 case 'r':
1180 rflag++;
1181 tflag++;
1182 break;
1183 case 't':
1184 tflag++;
1185 break;
1186 case 'T':
1187 dtime++;
1188 break;
1189 case 'x':
1190 xflag++;
1191 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001192 case 'y':
1193 show_fd_path = 1;
1194 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195 case 'v':
1196 qualify("abbrev=none");
1197 break;
1198 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001199 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200 exit(0);
1201 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001202 case 'z':
1203 not_failing_only = 1;
1204 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 case 'a':
1206 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001207 if (acolumn < 0)
1208 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 break;
1210 case 'e':
1211 qualify(optarg);
1212 break;
1213 case 'o':
1214 outfname = strdup(optarg);
1215 break;
1216 case 'O':
1217 set_overhead(atoi(optarg));
1218 break;
1219 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001220 pid = atoi(optarg);
1221 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001222 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223 break;
1224 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001225 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001226 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227 break;
1228 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001229 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230 tcp->flags |= TCB_ATTACHED;
1231 pflag_seen++;
1232 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001233 case 'P':
1234 tracing_paths = 1;
1235 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001236 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001237 }
1238 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 case 's':
1240 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001241 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001242 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001243 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244 break;
1245 case 'S':
1246 set_sortby(optarg);
1247 break;
1248 case 'u':
1249 username = strdup(optarg);
1250 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001251 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001252 if (putenv(optarg) < 0)
1253 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001254 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001255 case 'I':
1256 opt_intr = atoi(optarg);
1257 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1258 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1259 }
1260 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 default:
1262 usage(stderr, 1);
1263 break;
1264 }
1265 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001266 argv += optind;
1267 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268
Denys Vlasenko102ec492011-08-25 01:27:59 +02001269 acolumn_spaces = malloc(acolumn + 1);
1270 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001271 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001272 memset(acolumn_spaces, ' ', acolumn);
1273 acolumn_spaces[acolumn] = '\0';
1274
Denys Vlasenko837399a2012-01-24 11:37:03 +01001275 /* Must have PROG [ARGS], or -p PID. Not both. */
1276 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001277 usage(stderr, 1);
1278
Wang Chaod322a4b2010-08-05 14:30:11 +08001279 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001280 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001281 }
1282
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001283 if (!followfork)
1284 followfork = optF;
1285
Roland McGrathcb9def62006-04-25 07:48:03 +00001286 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001287 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001288 }
1289
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290 /* See if they want to run as another user. */
1291 if (username != NULL) {
1292 struct passwd *pent;
1293
1294 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001295 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001297 pent = getpwnam(username);
1298 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001299 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001300 }
1301 run_uid = pent->pw_uid;
1302 run_gid = pent->pw_gid;
1303 }
1304 else {
1305 run_uid = getuid();
1306 run_gid = getgid();
1307 }
1308
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001309#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001310 if (followfork)
1311 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001312 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001313 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001314#endif
1315
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 /* Check if they want to redirect the output. */
1317 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001318 /* See if they want to pipe the output. */
1319 if (outfname[0] == '|' || outfname[0] == '!') {
1320 /*
1321 * We can't do the <outfname>.PID funny business
1322 * when using popen, so prohibit it.
1323 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001324 if (followfork > 1)
1325 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1326 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001327 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001328 else if (followfork <= 1)
1329 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 }
1331
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001332 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001333 char *buf = malloc(BUFSIZ);
1334 if (!buf)
1335 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001337 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001338 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001339 if (!opt_intr)
1340 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001342 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001343 if (!opt_intr)
1344 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001345
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001346 /* argv[0] -pPID -oFILE Default interactive setting
1347 * yes 0 0 INTR_WHILE_WAIT
1348 * no 1 0 INTR_WHILE_WAIT
1349 * yes 0 1 INTR_NEVER
1350 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001351 */
1352
1353 /* STARTUP_CHILD must be called before the signal handlers get
1354 installed below as they are inherited into the spawned process.
1355 Also we do not need to be protected by them as during interruption
1356 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001357 if (argv[0])
1358 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 sigemptyset(&empty_set);
1361 sigemptyset(&blocked_set);
1362 sa.sa_handler = SIG_IGN;
1363 sigemptyset(&sa.sa_mask);
1364 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001365 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1366 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1367 if (opt_intr != INTR_ANYWHERE) {
1368 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1369 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1370 /*
1371 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1372 * fatal signals are blocked while syscall stop is processed,
1373 * and acted on in between, when waiting for new syscall stops.
1374 * In non-interactive mode, signals are ignored.
1375 */
1376 if (opt_intr == INTR_WHILE_WAIT) {
1377 sigaddset(&blocked_set, SIGHUP);
1378 sigaddset(&blocked_set, SIGINT);
1379 sigaddset(&blocked_set, SIGQUIT);
1380 sigaddset(&blocked_set, SIGPIPE);
1381 sigaddset(&blocked_set, SIGTERM);
1382 sa.sa_handler = interrupt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001383#ifdef SUNOS4
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001384 /* POSIX signals on sunos4.1 are a little broken. */
1385 sa.sa_flags = SA_INTERRUPT;
1386#endif
1387 }
1388 /* SIG_IGN, or set handler for these */
1389 sigaction(SIGHUP, &sa, NULL);
1390 sigaction(SIGINT, &sa, NULL);
1391 sigaction(SIGQUIT, &sa, NULL);
1392 sigaction(SIGPIPE, &sa, NULL);
1393 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001394 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001395#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 sa.sa_handler = reaper;
1397 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001398#else
1399 /* Make sure SIGCHLD has the default action so that waitpid
1400 definitely works without losing track of children. The user
1401 should not have given us a bogus state to inherit, but he might
1402 have. Arguably we should detect SIG_IGN here and pass it on
1403 to children, but probably noone really needs that. */
1404 sa.sa_handler = SIG_DFL;
1405 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001406#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001408 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001409 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001410
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411 if (trace() < 0)
1412 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001413
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001415 fflush(NULL);
1416 if (exit_code > 0xff) {
1417 /* Child was killed by a signal, mimic that. */
1418 exit_code &= 0xff;
1419 signal(exit_code, SIG_DFL);
1420 raise(exit_code);
1421 /* Paranoia - what if this signal is not fatal?
1422 Exit with 128 + signo then. */
1423 exit_code += 128;
1424 }
1425 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426}
1427
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001428static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001429expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001430{
1431 /* Allocate some more TCBs and expand the table.
1432 We don't want to relocate the TCBs because our
1433 callers have pointers and it would be a pain.
1434 So tcbtab is a table of pointers. Since we never
1435 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001436 int i = tcbtabsize;
1437 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1438 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001439 if (!newtab || !newtcbs)
1440 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001441 tcbtabsize *= 2;
1442 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001443 while (i < tcbtabsize)
1444 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001445}
1446
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001448alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449{
1450 int i;
1451 struct tcb *tcp;
1452
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001453 if (nprocs == tcbtabsize)
1454 expand_tcbtab();
1455
Roland McGrathee9d4352002-12-18 04:16:10 +00001456 for (i = 0; i < tcbtabsize; i++) {
1457 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001459 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001461 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001463#if SUPPORTED_PERSONALITIES > 1
1464 tcp->currpers = current_personality;
1465#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001466#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001468#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001470 if (debug)
1471 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001472 if (command_options_parsed)
1473 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474 return tcp;
1475 }
1476 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001477 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001478}
1479
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001480#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001482proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483{
1484 char proc[32];
1485 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001486#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001487 int i;
1488 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489 sigset_t signals;
1490 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001491#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492#ifndef HAVE_POLLABLE_PROCFS
1493 static int last_pfd;
1494#endif
1495
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001496#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001497 /* Open the process pseudo-files in /proc. */
1498 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001499 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1500 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501 perror("strace: open(\"/proc/...\", ...)");
1502 return -1;
1503 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001504 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001505 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001506 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1507 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001508 perror("strace: open(\"/proc/...\", ...)");
1509 return -1;
1510 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001511 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001512 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001513 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1514 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001515 perror("strace: open(\"/proc/...\", ...)");
1516 return -1;
1517 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001518 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001519#else
1520 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001521# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001522 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001523 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001524# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001525 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001526 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001527# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001528 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001529 perror("strace: open(\"/proc/...\", ...)");
1530 return -1;
1531 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001532 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001533#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001534#ifdef FREEBSD
1535 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001536 tcp->pfd_reg = open(proc, O_RDONLY);
1537 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001538 perror("strace: open(\"/proc/.../regs\", ...)");
1539 return -1;
1540 }
1541 if (cflag) {
1542 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001543 tcp->pfd_status = open(proc, O_RDONLY);
1544 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001545 perror("strace: open(\"/proc/.../status\", ...)");
1546 return -1;
1547 }
1548 } else
1549 tcp->pfd_status = -1;
1550#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001551 rebuild_pollv();
1552 if (!attaching) {
1553 /*
1554 * Wait for the child to pause. Because of a race
1555 * condition we have to poll for the event.
1556 */
1557 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001558 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001559 perror("strace: PIOCSTATUS");
1560 return -1;
1561 }
1562 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001563 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001564 }
1565 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001566#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001567 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001568 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001569 perror("strace: PIOCSTOP");
1570 return -1;
1571 }
Roland McGrath553a6092002-12-16 20:40:39 +00001572#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573#ifdef PIOCSET
1574 /* Set Run-on-Last-Close. */
1575 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001576 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577 perror("PIOCSET PR_RLC");
1578 return -1;
1579 }
1580 /* Set or Reset Inherit-on-Fork. */
1581 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001582 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583 perror("PIOC{SET,RESET} PR_FORK");
1584 return -1;
1585 }
1586#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001587#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1589 perror("PIOCSRLC");
1590 return -1;
1591 }
1592 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1593 perror("PIOC{S,R}FORK");
1594 return -1;
1595 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001596#else /* FREEBSD */
1597 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1598 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1599 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001600 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001601 }
1602 arg &= ~PF_LINGER;
1603 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001604 perror("PIOCSFL");
1605 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001606 }
1607#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001609#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001610 /* Enable all syscall entries we care about. */
1611 premptyset(&syscalls);
1612 for (i = 1; i < MAX_QUALS; ++i) {
1613 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001614 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001615 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001616 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001617 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001618 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001619#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001620 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001621#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001622#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001623 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001624#endif
1625#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001626 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001627#endif
1628#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001629 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001630#endif
1631 }
1632 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 perror("PIOCSENTRY");
1634 return -1;
1635 }
John Hughes19e49982001-10-19 08:59:12 +00001636 /* Enable the syscall exits. */
1637 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 perror("PIOSEXIT");
1639 return -1;
1640 }
John Hughes19e49982001-10-19 08:59:12 +00001641 /* Enable signals we care about. */
1642 premptyset(&signals);
1643 for (i = 1; i < MAX_QUALS; ++i) {
1644 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001645 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001646 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001647 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 perror("PIOCSTRACE");
1649 return -1;
1650 }
John Hughes19e49982001-10-19 08:59:12 +00001651 /* Enable faults we care about */
1652 premptyset(&faults);
1653 for (i = 1; i < MAX_QUALS; ++i) {
1654 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001655 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001656 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001657 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658 perror("PIOCSFAULT");
1659 return -1;
1660 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001661#else /* FREEBSD */
1662 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001663 arg = S_SIG | S_SCE | S_SCX;
1664 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001665 perror("PIOCBIS");
1666 return -1;
1667 }
1668#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669 if (!attaching) {
1670#ifdef MIPS
1671 /*
1672 * The SGI PRSABORT doesn't work for pause() so
1673 * we send it a caught signal to wake it up.
1674 */
1675 kill(tcp->pid, SIGINT);
1676#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001677#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001679 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001680 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 perror("PIOCRUN");
1682 return -1;
1683 }
Roland McGrath553a6092002-12-16 20:40:39 +00001684#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001685#endif /* !MIPS*/
1686#ifdef FREEBSD
1687 /* wake up the child if it received the SIGSTOP */
1688 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001689#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 for (;;) {
1691 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001692 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 perror("PIOCWSTOP");
1694 return -1;
1695 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001696 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001697 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001698 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001699 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700 break;
1701 }
1702 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001703#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001704 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001705 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1706#else
1707 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1708#endif
1709 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710 perror("PIOCRUN");
1711 return -1;
1712 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001713#ifdef FREEBSD
1714 /* handle the case where we "opened" the child before
1715 it did the kill -STOP */
1716 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1717 tcp->status.PR_WHAT == SIGSTOP)
1718 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001719#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720 }
1721 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001722#ifdef FREEBSD
1723 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001724 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001725 /* We are attaching to an already running process.
1726 * Try to figure out the state of the process in syscalls,
1727 * to handle the first event well.
1728 * This is done by having a look at the "wchan" property of the
1729 * process, which tells where it is stopped (if it is). */
1730 FILE * status;
1731 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001732
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001733 sprintf(proc, "/proc/%d/status", tcp->pid);
1734 status = fopen(proc, "r");
1735 if (status &&
1736 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1737 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1738 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1739 strcmp(wchan, "stopevent")) {
1740 /* The process is asleep in the middle of a syscall.
1741 Fake the syscall entry event */
1742 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1743 tcp->status.PR_WHY = PR_SYSENTRY;
1744 trace_syscall(tcp);
1745 }
1746 if (status)
1747 fclose(status);
1748 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001749 }
1750#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751#ifndef HAVE_POLLABLE_PROCFS
1752 if (proc_poll_pipe[0] != -1)
1753 proc_poller(tcp->pfd);
1754 else if (nprocs > 1) {
1755 proc_poll_open();
1756 proc_poller(last_pfd);
1757 proc_poller(tcp->pfd);
1758 }
1759 last_pfd = tcp->pfd;
1760#endif /* !HAVE_POLLABLE_PROCFS */
1761 return 0;
1762}
1763
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001764#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001766static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001767pid2tcb(int pid)
1768{
1769 int i;
1770
1771 if (pid <= 0)
1772 return NULL;
1773
1774 for (i = 0; i < tcbtabsize; i++) {
1775 struct tcb *tcp = tcbtab[i];
1776 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1777 return tcp;
1778 }
1779
1780 return NULL;
1781}
1782
1783#ifdef USE_PROCFS
1784
1785static struct tcb *
1786first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787{
1788 int i;
1789 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001790 for (i = 0; i < tcbtabsize; i++) {
1791 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 if (tcp->flags & TCB_INUSE)
1793 return tcp;
1794 }
1795 return NULL;
1796}
1797
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001799pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800{
1801 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802
Roland McGrathca16be82003-01-10 19:55:28 +00001803 for (i = 0; i < tcbtabsize; i++) {
1804 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 if (tcp->pfd != pfd)
1806 continue;
1807 if (tcp->flags & TCB_INUSE)
1808 return tcp;
1809 }
1810 return NULL;
1811}
1812
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001813#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001814
1815void
Denys Vlasenko12014262011-05-30 14:00:14 +02001816droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817{
1818 if (tcp->pid == 0)
1819 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001820
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001822 if (debug)
1823 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001824
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001825#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826 if (tcp->pfd != -1) {
1827 close(tcp->pfd);
1828 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001829# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001830 if (tcp->pfd_reg != -1) {
1831 close(tcp->pfd_reg);
1832 tcp->pfd_reg = -1;
1833 }
1834 if (tcp->pfd_status != -1) {
1835 close(tcp->pfd_status);
1836 tcp->pfd_status = -1;
1837 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001838# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001839 tcp->flags = 0; /* rebuild_pollv needs it */
1840 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001842#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001843
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001844 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001846
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001847 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848}
1849
Roland McGrath0a463882007-07-05 18:43:16 +00001850/* detach traced process; continue with sig
1851 Never call DETACH twice on the same process as both unattached and
1852 attached-unstopped processes give the same ESRCH. For unattached process we
1853 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001854
1855static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001856detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857{
1858 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001859#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001860 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001861#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862
1863 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001864 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865
1866#ifdef LINUX
1867 /*
1868 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001869 * before detaching. Arghh. We go through hoops
1870 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001872#if defined(SPARC)
1873#undef PTRACE_DETACH
1874#define PTRACE_DETACH PTRACE_SUNDETACH
1875#endif
Roland McGrath02203312007-06-11 22:06:31 +00001876 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001877 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001878 * We must catch exactly one as otherwise the detached process
1879 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001880 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001881 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001882 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001883 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001885 }
1886 else if (errno != ESRCH) {
1887 /* Shouldn't happen. */
1888 perror("detach: ptrace(PTRACE_DETACH, ...)");
1889 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001890 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001891 if (errno != ESRCH)
1892 perror("detach: checking sanity");
1893 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001894 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001895 if (errno != ESRCH)
1896 perror("detach: stopping child");
1897 }
Roland McGrath02203312007-06-11 22:06:31 +00001898 else
1899 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001900 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001902#ifdef __WALL
1903 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1904 if (errno == ECHILD) /* Already gone. */
1905 break;
1906 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001907 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001908 break;
1909 }
1910#endif /* __WALL */
1911 /* No __WALL here. */
1912 if (waitpid(tcp->pid, &status, 0) < 0) {
1913 if (errno != ECHILD) {
1914 perror("detach: waiting");
1915 break;
1916 }
1917#ifdef __WCLONE
1918 /* If no processes, try clones. */
1919 if (wait4(tcp->pid, &status, __WCLONE,
1920 NULL) < 0) {
1921 if (errno != ECHILD)
1922 perror("detach: waiting");
1923 break;
1924 }
1925#endif /* __WCLONE */
1926 }
1927#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001928 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001929#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930 if (!WIFSTOPPED(status)) {
1931 /* Au revoir, mon ami. */
1932 break;
1933 }
1934 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001935 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 break;
1937 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001938 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001939 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001940 : WSTOPSIG(status));
1941 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001943 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001944 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001945#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946
1947#if defined(SUNOS4)
1948 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001949 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950#endif /* SUNOS4 */
1951
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 if (!qflag)
1953 fprintf(stderr, "Process %u detached\n", tcp->pid);
1954
1955 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001956
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 return error;
1958}
1959
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001960#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001962static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001963{
1964 int pid;
1965 int status;
1966
1967 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001968 }
1969}
1970
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001971#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001972
1973static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001974cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975{
1976 int i;
1977 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001978 int fatal_sig;
1979
1980 /* 'interrupted' is a volatile object, fetch it only once */
1981 fatal_sig = interrupted;
1982 if (!fatal_sig)
1983 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984
Roland McGrathee9d4352002-12-18 04:16:10 +00001985 for (i = 0; i < tcbtabsize; i++) {
1986 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001987 if (!(tcp->flags & TCB_INUSE))
1988 continue;
1989 if (debug)
1990 fprintf(stderr,
1991 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001992 if (printing_tcp &&
1993 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1994 tprints(" <unfinished ...>\n");
1995 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001996 }
1997 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001998 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001999 else {
2000 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01002001 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002 }
2003 }
2004 if (cflag)
2005 call_summary(outf);
2006}
2007
2008static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002009interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01002011 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012}
2013
2014#ifndef HAVE_STRERROR
2015
Roland McGrath6d2b3492002-12-30 00:51:30 +00002016#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017extern int sys_nerr;
2018extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00002019#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002020
2021const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002022strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002023{
2024 static char buf[64];
2025
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002026 if (err_no < 1 || err_no >= sys_nerr) {
2027 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 return buf;
2029 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002030 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031}
2032
2033#endif /* HAVE_STERRROR */
2034
2035#ifndef HAVE_STRSIGNAL
2036
Roland McGrath8f474e02003-01-14 07:53:33 +00002037#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00002038extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00002040#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
2041extern char *_sys_siglist[];
2042#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002043
2044const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002045strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046{
2047 static char buf[64];
2048
2049 if (sig < 1 || sig >= NSIG) {
2050 sprintf(buf, "Unknown signal %d", sig);
2051 return buf;
2052 }
2053#ifdef HAVE__SYS_SIGLIST
2054 return _sys_siglist[sig];
2055#else
2056 return sys_siglist[sig];
2057#endif
2058}
2059
2060#endif /* HAVE_STRSIGNAL */
2061
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002062#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063
2064static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002065rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002066{
2067 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02002069 free(pollv);
2070 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02002071 if (!pollv)
2072 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00002073
Roland McGrathca16be82003-01-10 19:55:28 +00002074 for (i = j = 0; i < tcbtabsize; i++) {
2075 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002076 if (!(tcp->flags & TCB_INUSE))
2077 continue;
2078 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002079 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080 j++;
2081 }
2082 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002083 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002084 }
2085}
2086
2087#ifndef HAVE_POLLABLE_PROCFS
2088
2089static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002090proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 int i;
2093
2094 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002095 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002096 }
2097 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02002098 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 }
2100}
2101
2102static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002103proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104{
2105 int i;
2106 int n;
2107 struct proc_pollfd pollinfo;
2108
Denys Vlasenko5d645812011-08-20 12:48:18 +02002109 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
2110 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111 return n;
2112 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002113 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 }
2115 for (i = 0; i < nprocs; i++) {
2116 if (pollv[i].fd == pollinfo.fd)
2117 pollv[i].revents = pollinfo.revents;
2118 else
2119 pollv[i].revents = 0;
2120 }
2121 poller_pid = pollinfo.pid;
2122 return 1;
2123}
2124
2125static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002126wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127{
2128}
2129
2130static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002131proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132{
2133 struct proc_pollfd pollinfo;
2134 struct sigaction sa;
2135 sigset_t blocked_set, empty_set;
2136 int i;
2137 int n;
2138 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002139#ifdef FREEBSD
2140 struct procfs_status pfs;
2141#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142
2143 switch (fork()) {
2144 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002145 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 case 0:
2147 break;
2148 default:
2149 return;
2150 }
2151
2152 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2153 sa.sa_flags = 0;
2154 sigemptyset(&sa.sa_mask);
2155 sigaction(SIGHUP, &sa, NULL);
2156 sigaction(SIGINT, &sa, NULL);
2157 sigaction(SIGQUIT, &sa, NULL);
2158 sigaction(SIGPIPE, &sa, NULL);
2159 sigaction(SIGTERM, &sa, NULL);
2160 sa.sa_handler = wakeup_handler;
2161 sigaction(SIGUSR1, &sa, NULL);
2162 sigemptyset(&blocked_set);
2163 sigaddset(&blocked_set, SIGUSR1);
2164 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2165 sigemptyset(&empty_set);
2166
2167 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002168 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002169 }
2170 n = rl.rlim_cur;
2171 for (i = 0; i < n; i++) {
2172 if (i != pfd && i != proc_poll_pipe[1])
2173 close(i);
2174 }
2175
2176 pollinfo.fd = pfd;
2177 pollinfo.pid = getpid();
2178 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002179#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002180 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2181#else
2182 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2183#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002184 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002185 switch (errno) {
2186 case EINTR:
2187 continue;
2188 case EBADF:
2189 pollinfo.revents = POLLERR;
2190 break;
2191 case ENOENT:
2192 pollinfo.revents = POLLHUP;
2193 break;
2194 default:
2195 perror("proc_poller: PIOCWSTOP");
2196 }
2197 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2198 _exit(0);
2199 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002200 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2202 sigsuspend(&empty_set);
2203 }
2204}
2205
2206#endif /* !HAVE_POLLABLE_PROCFS */
2207
2208static int
2209choose_pfd()
2210{
2211 int i, j;
2212 struct tcb *tcp;
2213
2214 static int last;
2215
2216 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002217 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 /*
2219 * The previous process is ready to run again. We'll
2220 * let it do so if it is currently in a syscall. This
2221 * heuristic improves the readability of the trace.
2222 */
2223 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002224 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225 return pollv[last].fd;
2226 }
2227
2228 for (i = 0; i < nprocs; i++) {
2229 /* Let competing children run round robin. */
2230 j = (i + last + 1) % nprocs;
2231 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2232 tcp = pfd2tcb(pollv[j].fd);
2233 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002234 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002235 }
2236 droptcb(tcp);
2237 return -1;
2238 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002239 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002240 last = j;
2241 return pollv[j].fd;
2242 }
2243 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002244 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245}
2246
2247static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002248trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002249{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002250#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002251 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002252#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002253 struct tcb *tcp;
2254 int pfd;
2255 int what;
2256 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002257 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002258
2259 for (;;) {
2260 if (interactive)
2261 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2262
2263 if (nprocs == 0)
2264 break;
2265
2266 switch (nprocs) {
2267 case 1:
2268#ifndef HAVE_POLLABLE_PROCFS
2269 if (proc_poll_pipe[0] == -1) {
2270#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002271 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002272 if (!tcp)
2273 continue;
2274 pfd = tcp->pfd;
2275 if (pfd == -1)
2276 continue;
2277 break;
2278#ifndef HAVE_POLLABLE_PROCFS
2279 }
2280 /* fall through ... */
2281#endif /* !HAVE_POLLABLE_PROCFS */
2282 default:
2283#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002284#ifdef POLL_HACK
2285 /* On some systems (e.g. UnixWare) we get too much ugly
2286 "unfinished..." stuff when multiple proceses are in
2287 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002288
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002289 if (in_syscall) {
2290 struct pollfd pv;
2291 tcp = in_syscall;
2292 in_syscall = NULL;
2293 pv.fd = tcp->pfd;
2294 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002295 what = poll(&pv, 1, 1);
2296 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002297 if (interrupted)
2298 return 0;
2299 continue;
2300 }
2301 else if (what == 1 && pv.revents & POLLWANT) {
2302 goto FOUND;
2303 }
2304 }
2305#endif
2306
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002307 if (poll(pollv, nprocs, INFTIM) < 0) {
2308 if (interrupted)
2309 return 0;
2310 continue;
2311 }
2312#else /* !HAVE_POLLABLE_PROCFS */
2313 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2314 if (interrupted)
2315 return 0;
2316 continue;
2317 }
2318#endif /* !HAVE_POLLABLE_PROCFS */
2319 pfd = choose_pfd();
2320 if (pfd == -1)
2321 continue;
2322 break;
2323 }
2324
2325 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002326 tcp = pfd2tcb(pfd);
2327 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002328 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 }
John Hughesb6643082002-05-23 11:02:22 +00002330#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002331 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002332#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333 /* Get the status of the process. */
2334 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002335#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002336 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002337#else /* FREEBSD */
2338 /* Thanks to some scheduling mystery, the first poller
2339 sometimes waits for the already processed end of fork
2340 event. Doing a non blocking poll here solves the problem. */
2341 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002342 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002343 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002344 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002345#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002346 ioctl_errno = errno;
2347#ifndef HAVE_POLLABLE_PROCFS
2348 if (proc_poll_pipe[0] != -1) {
2349 if (ioctl_result < 0)
2350 kill(poller_pid, SIGKILL);
2351 else
2352 kill(poller_pid, SIGUSR1);
2353 }
2354#endif /* !HAVE_POLLABLE_PROCFS */
2355 }
2356 if (interrupted)
2357 return 0;
2358
2359 if (interactive)
2360 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2361
2362 if (ioctl_result < 0) {
2363 /* Find out what happened if it failed. */
2364 switch (ioctl_errno) {
2365 case EINTR:
2366 case EBADF:
2367 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002368#ifdef FREEBSD
2369 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002370#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002371 case ENOENT:
2372 droptcb(tcp);
2373 continue;
2374 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002375 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 }
2377 }
2378
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002379#ifdef FREEBSD
2380 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2381 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002382 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002383 continue;
2384 }
Roland McGrath553a6092002-12-16 20:40:39 +00002385#endif
2386
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 /* clear the just started flag */
2388 tcp->flags &= ~TCB_STARTUP;
2389
2390 /* set current output file */
2391 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002392 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002393
2394 if (cflag) {
2395 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002396#ifdef FREEBSD
2397 char buf[1024];
2398 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002399
Denys Vlasenko5d645812011-08-20 12:48:18 +02002400 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2401 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002402 buf[len] = '\0';
2403 sscanf(buf,
2404 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2405 &stime.tv_sec, &stime.tv_usec);
2406 } else
2407 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002408#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002409 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2410 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002411#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002412 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2413 tcp->stime = stime;
2414 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002415 what = tcp->status.PR_WHAT;
2416 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002417#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002418 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002419 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2420 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002421 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002422 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002423 }
2424 }
2425 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002426#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002427 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002428#ifdef POLL_HACK
2429 in_syscall = tcp;
2430#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002431 case PR_SYSEXIT:
2432 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002433 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 }
2435 break;
2436 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002437 if (cflag != CFLAG_ONLY_STATS
2438 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002439 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002440 tprintf("--- %s (%s) ---\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002441 signame(what), strsignal(what));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002442 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002443#ifdef PR_INFO
2444 if (tcp->status.PR_INFO.si_signo == what) {
2445 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002446 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002447 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002448 tprints("\n");
2449 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002450 }
2451#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002452 }
2453 break;
2454 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002455 if (cflag != CFLAGS_ONLY_STATS
2456 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002457 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002458 tprintf("=== FAULT %d ===\n", what);
2459 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002460 }
2461 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002462#ifdef FREEBSD
2463 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002464 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002465#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002466 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002467 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002468 break;
2469 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002470 /* Remember current print column before continuing. */
2471 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002472 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002473#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002474 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002475#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002476 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002477#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002478 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002479 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480 }
2481 }
2482 return 0;
2483}
2484
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002485#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002486
Roland McGratheb9e2e82009-06-02 16:49:22 -07002487static int
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002488trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002489{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002490#ifdef LINUX
2491 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002492 struct rusage *rup = cflag ? &ru : NULL;
2493# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002494 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002495# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002496#endif /* LINUX */
2497
Roland McGratheb9e2e82009-06-02 16:49:22 -07002498 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002499 int pid;
2500 int wait_errno;
2501 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002502 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002503 struct tcb *tcp;
2504 unsigned event;
2505
Denys Vlasenko222713a2009-03-17 14:29:59 +00002506 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002507 return 0;
2508 if (interactive)
2509 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002511# ifdef __WALL
2512 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002513 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002514 /* this kernel does not support __WALL */
2515 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002516 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002517 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002518 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002519 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002520 pid = wait4(-1, &status, __WCLONE, rup);
2521 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002522 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002523 }
2524 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002525# else
2526 pid = wait4(-1, &status, 0, rup);
2527# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002528#endif /* LINUX */
2529#ifdef SUNOS4
2530 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002531#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002532 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002533 if (interactive)
2534 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002535
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002536 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002537 switch (wait_errno) {
2538 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002540 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002541 /*
2542 * We would like to verify this case
2543 * but sometimes a race in Solbourne's
2544 * version of SunOS sometimes reports
2545 * ECHILD before sending us SIGCHILD.
2546 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002547 return 0;
2548 default:
2549 errno = wait_errno;
2550 perror("strace: wait");
2551 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002552 }
2553 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002554 if (pid == popen_pid) {
2555 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002556 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002557 continue;
2558 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002559
2560 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002561 if (debug) {
2562 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2563#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002564 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002565 static const char *const event_names[] = {
2566 [PTRACE_EVENT_CLONE] = "CLONE",
2567 [PTRACE_EVENT_FORK] = "FORK",
2568 [PTRACE_EVENT_VFORK] = "VFORK",
2569 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2570 [PTRACE_EVENT_EXEC] = "EXEC",
2571 [PTRACE_EVENT_EXIT] = "EXIT",
2572 };
2573 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002574 if (event < ARRAY_SIZE(event_names))
2575 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002576 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002577 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002578 e = buf;
2579 }
2580 fprintf(stderr, " PTRACE_EVENT_%s", e);
2581 }
2582#endif
2583 strcpy(buf, "???");
2584 if (WIFSIGNALED(status))
2585#ifdef WCOREDUMP
2586 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2587 WCOREDUMP(status) ? "core," : "",
2588 signame(WTERMSIG(status)));
2589#else
2590 sprintf(buf, "WIFSIGNALED,sig=%s",
2591 signame(WTERMSIG(status)));
2592#endif
2593 if (WIFEXITED(status))
2594 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2595 if (WIFSTOPPED(status))
2596 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002597#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002598 if (WIFCONTINUED(status))
2599 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002600#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002601 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2602 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002603
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002604 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002605 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002606
2607#ifdef LINUX
2608 /* Under Linux, execve changes pid to thread leader's pid,
2609 * and we see this changed pid on EVENT_EXEC and later,
2610 * execve sysexit. Leader "disappears" without exit
2611 * notification. Let user know that, drop leader's tcb,
2612 * and fix up pid in execve thread's tcb.
2613 * Effectively, execve thread's tcb replaces leader's tcb.
2614 *
2615 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2616 * on exit syscall) in multithreaded programs exactly
2617 * in order to handle this case.
2618 *
2619 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2620 * On 2.6 and earlier, it can return garbage.
2621 */
2622 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2623 long old_pid = 0;
2624 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2625 && old_pid > 0
2626 && old_pid != pid
2627 ) {
2628 struct tcb *execve_thread = pid2tcb(old_pid);
2629 if (tcp) {
2630 outf = tcp->outf;
2631 curcol = tcp->curcol;
2632 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002633 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002634 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002635 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002636 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2637 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002638 fflush(outf);
2639 }
2640 if (execve_thread) {
2641 /* swap output FILEs (needed for -ff) */
2642 tcp->outf = execve_thread->outf;
2643 execve_thread->outf = outf;
2644 }
2645 droptcb(tcp);
2646 }
2647 tcp = execve_thread;
2648 if (tcp) {
2649 tcp->pid = pid;
2650 tcp->flags |= TCB_REPRINT;
2651 }
2652 }
2653 }
2654#endif
2655
Denys Vlasenko5d645812011-08-20 12:48:18 +02002656 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002657#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002658 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002659 /* This is needed to go with the CLONE_PTRACE
2660 changes in process.c/util.c: we might see
2661 the child's initial trap before we see the
2662 parent return from the clone syscall.
2663 Leave the child suspended until the parent
2664 returns from its system call. Only then
2665 will we have the association of parent and
2666 child so that we know how to do clearbpt
2667 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002668 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002669 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002670 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002671 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002672 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002673 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002674 else
2675 /* This can happen if a clone call used
2676 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002677#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002678 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002679 if (WIFSTOPPED(status))
2680 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002681 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002682 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002683 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002684 /* set current output file */
2685 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002686 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002687#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002688 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002689 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2690 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002692#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002693
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002695 if (pid == strace_child)
2696 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002697 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002698 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2699 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002700#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002701 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002702 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002703 WCOREDUMP(status) ? "(core dumped) " : "");
2704#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002705 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002706 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002707#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01002708 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002709 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002710 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711 droptcb(tcp);
2712 continue;
2713 }
2714 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002715 if (pid == strace_child)
2716 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002717 if (tcp == printing_tcp) {
2718 tprints(" <unfinished ...>\n");
2719 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00002720 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002721 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2722 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002723 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2724 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002725 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002726 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002727 droptcb(tcp);
2728 continue;
2729 }
2730 if (!WIFSTOPPED(status)) {
2731 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2732 droptcb(tcp);
2733 continue;
2734 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002735
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002736 /* Is this the very first time we see this tracee stopped? */
2737 if (tcp->flags & TCB_STARTUP) {
2738 if (debug)
2739 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002740 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002741 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002742 /*
2743 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002744 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002745 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002746 if (clearbpt(tcp) < 0) {
2747 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002748 droptcb(tcp);
2749 cleanup();
2750 return -1;
2751 }
2752 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002753#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002754 if (ptrace_setoptions) {
2755 if (debug)
2756 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2757 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2758 if (errno != ESRCH) {
2759 /* Should never happen, really */
2760 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002761 }
2762 }
2763 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002764#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002765 }
2766
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002767 sig = WSTOPSIG(status);
2768
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002769 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002770 /* Ptrace event */
2771#ifdef USE_SEIZE
2772 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002773 /*
2774 * PTRACE_INTERRUPT-stop or group-stop.
2775 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2776 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002777 if (sig == SIGSTOP
2778 || sig == SIGTSTP
2779 || sig == SIGTTIN
2780 || sig == SIGTTOU
2781 ) {
2782 stopped = 1;
2783 goto show_stopsig;
2784 }
2785 }
2786#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002787 goto restart_tracee_with_sig_0;
2788 }
2789
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002790 /* Is this post-attach SIGSTOP?
2791 * Interestingly, the process may stop
2792 * with STOPSIG equal to some other signal
2793 * than SIGSTOP if we happend to attach
2794 * just before the process takes a signal.
2795 */
2796 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2797 if (debug)
2798 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2799 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002800 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002801 }
2802
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002803 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002804 siginfo_t si;
2805
2806 /* Nonzero (true) if tracee is stopped by signal
2807 * (as opposed to "tracee received signal").
2808 */
2809 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002810#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002811 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002812#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002813 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002814 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002815#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002816 long pc = 0;
2817 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002818
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002819 upeek(tcp, PT_CR_IPSR, &psr);
2820 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002821
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002822# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002823 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002824# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002825# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002826#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002827# define PC_FORMAT_STR ""
2828# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002829#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002830 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002831 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002832 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002833 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002834 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002835 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002836 PC_FORMAT_ARG);
2837 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002838 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002839 strsignal(sig),
2840 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002841 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002842 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002843 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002844 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002845
2846 if (!stopped)
2847 /* It's signal-delivery-stop. Inject the signal */
2848 goto restart_tracee;
2849
2850 /* It's group-stop */
2851#ifdef USE_SEIZE
2852 if (use_seize) {
2853 /*
2854 * This ends ptrace-stop, but does *not* end group-stop.
2855 * This makes stopping signals work properly on straced process
2856 * (that is, process really stops. It used to continue to run).
2857 */
2858 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2859 cleanup();
2860 return -1;
2861 }
2862 continue;
2863 }
2864 /* We don't have PTRACE_LISTEN support... */
2865#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002866 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002867 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002868
2869 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002870 if (interrupted)
2871 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002872
2873 /* This should be syscall entry or exit.
2874 * (Or it still can be that pesky post-execve SIGTRAP!)
2875 * Handle it.
2876 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002877 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2878 /* ptrace() failed in trace_syscall() with ESRCH.
2879 * Likely a result of process disappearing mid-flight.
2880 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002881 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002882 */
2883 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002884 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002885 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002886 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002887 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002888 printing_tcp->flags |= TCB_REPRINT;
2889 tprints(" <unfinished ...>\n");
2890 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002891 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002892 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002893 /* We assume that ptrace error was caused by process death.
2894 * We used to detach(tcp) here, but since we no longer
2895 * implement "detach before death" policy/hack,
2896 * we can let this process to report its death to us
2897 * normally, via WIFEXITED or WIFSIGNALED wait status.
2898 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002899 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002900 /* It's our real child (and we also trace it) */
2901 /* my_tkill(pid, SIGKILL); - why? */
2902 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002903 }
2904 continue;
2905 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002906 restart_tracee_with_sig_0:
2907 sig = 0;
2908 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002909 /* Remember current print column before continuing. */
2910 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002911 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002912 cleanup();
2913 return -1;
2914 }
2915 }
2916 return 0;
2917}
2918
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002919#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002920
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002921void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002922tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002923{
2924 va_list args;
2925
Andreas Schwabe5355de2009-10-27 16:56:43 +01002926 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002927 if (outf) {
2928 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002929 if (n < 0) {
2930 if (outf != stderr)
2931 perror(outfname == NULL
2932 ? "<writing to pipe>" : outfname);
2933 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002934 curcol += n;
2935 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002936 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002937}
2938
2939void
2940tprints(const char *str)
2941{
2942 if (outf) {
2943 int n = fputs(str, outf);
2944 if (n >= 0) {
2945 curcol += strlen(str);
2946 return;
2947 }
2948 if (outf != stderr)
2949 perror(outfname == NULL
2950 ? "<writing to pipe>" : outfname);
2951 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002952}
2953
2954void
Denys Vlasenko12014262011-05-30 14:00:14 +02002955printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002956{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002957 if (printing_tcp) {
2958 if (printing_tcp->ptrace_errno) {
2959 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002960 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002961 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002962 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002963 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002964 printing_tcp->ptrace_errno = 0;
2965 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2966 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002967 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002968 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002969 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002970
2971 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002972 curcol = 0;
2973 if ((followfork == 1 || pflag_seen > 1) && outfname)
2974 tprintf("%-5d ", tcp->pid);
2975 else if (nprocs > 1 && !outfname)
2976 tprintf("[pid %5u] ", tcp->pid);
2977 if (tflag) {
2978 char str[sizeof("HH:MM:SS")];
2979 struct timeval tv, dtv;
2980 static struct timeval otv;
2981
2982 gettimeofday(&tv, NULL);
2983 if (rflag) {
2984 if (otv.tv_sec == 0)
2985 otv = tv;
2986 tv_sub(&dtv, &tv, &otv);
2987 tprintf("%6ld.%06ld ",
2988 (long) dtv.tv_sec, (long) dtv.tv_usec);
2989 otv = tv;
2990 }
2991 else if (tflag > 2) {
2992 tprintf("%ld.%06ld ",
2993 (long) tv.tv_sec, (long) tv.tv_usec);
2994 }
2995 else {
2996 time_t local = tv.tv_sec;
2997 strftime(str, sizeof(str), "%T", localtime(&local));
2998 if (tflag > 1)
2999 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
3000 else
3001 tprintf("%s ", str);
3002 }
3003 }
3004 if (iflag)
3005 printcall(tcp);
3006}
3007
3008void
Denys Vlasenko102ec492011-08-25 01:27:59 +02003009tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003010{
Denys Vlasenko102ec492011-08-25 01:27:59 +02003011 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02003012 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003013}
3014
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00003015#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003016
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003017int
3018mp_ioctl(int fd, int cmd, void *arg, int size)
3019{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003020 struct iovec iov[2];
3021 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00003022
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003023 iov[0].iov_base = &cmd;
3024 iov[0].iov_len = sizeof cmd;
3025 if (arg) {
3026 ++n;
3027 iov[1].iov_base = arg;
3028 iov[1].iov_len = size;
3029 }
Roland McGrath553a6092002-12-16 20:40:39 +00003030
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003031 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003032}
3033
3034#endif