blob: 493283135abd7ee70c1037a4bf4c2d3294ddde17 [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\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100205 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100206 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100207 [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\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100212-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213-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\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100222-T -- print time spent in each syscall\n\
223-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000224-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\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100226-h -- print help message\n\
227-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000228-a column -- alignment COLUMN for printing syscall results (default %d)\n\
229-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
230 options: trace, abbrev, verbose, raw, signal, read, or write\n\
231-o file -- send trace output to FILE instead of stderr\n\
232-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
233-p pid -- trace process with process id PID, may be repeated\n\
234-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
235-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
236-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000237-E var=val -- put var=val in the environment for command\n\
238-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000239-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000240" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000241-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000242 */
243, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 exit(exitval);
245}
246
Denys Vlasenko75422762011-05-27 14:36:01 +0200247static void die(void) __attribute__ ((noreturn));
248static void die(void)
249{
250 if (strace_tracer_pid == getpid()) {
251 cflag = 0;
252 cleanup();
253 }
254 exit(1);
255}
256
257static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200258{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100259 char *msg;
260
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000261 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100262
263 /* We want to print entire message with single fprintf to ensure
264 * message integrity if stderr is shared with other programs.
265 * Thus we use vasprintf + single fprintf.
266 */
267 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100268 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100269 if (err_no)
270 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
271 else
272 fprintf(stderr, "%s: %s\n", progname, msg);
273 free(msg);
274 } else {
275 /* malloc in vasprintf failed, try it without malloc */
276 fprintf(stderr, "%s: ", progname);
277 vfprintf(stderr, fmt, p);
278 if (err_no)
279 fprintf(stderr, ": %s\n", strerror(err_no));
280 else
281 putc('\n', stderr);
282 }
283 /* We don't switch stderr to buffered, thus fprintf(stderr)
284 * always flushes its output and this is not necessary: */
285 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200286}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200287
Denys Vlasenko75422762011-05-27 14:36:01 +0200288void error_msg(const char *fmt, ...)
289{
290 va_list p;
291 va_start(p, fmt);
292 verror_msg(0, fmt, p);
293 va_end(p);
294}
295
296void error_msg_and_die(const char *fmt, ...)
297{
298 va_list p;
299 va_start(p, fmt);
300 verror_msg(0, fmt, p);
301 die();
302}
303
304void perror_msg(const char *fmt, ...)
305{
306 va_list p;
307 va_start(p, fmt);
308 verror_msg(errno, fmt, p);
309 va_end(p);
310}
311
312void perror_msg_and_die(const char *fmt, ...)
313{
314 va_list p;
315 va_start(p, fmt);
316 verror_msg(errno, fmt, p);
317 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200318}
319
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200320void die_out_of_memory(void)
321{
322 static bool recursed = 0;
323 if (recursed)
324 exit(1);
325 recursed = 1;
326 error_msg_and_die("Out of memory");
327}
328
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000329#ifdef SVR4
330#ifdef MIPS
331void
332foobar()
333{
334}
335#endif /* MIPS */
336#endif /* SVR4 */
337
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400338/* Glue for systems without a MMU that cannot provide fork() */
339#ifdef HAVE_FORK
340# define strace_vforked 0
341#else
342# define strace_vforked 1
343# define fork() vfork()
344#endif
345
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100346#ifdef USE_SEIZE
347static int
348ptrace_attach_or_seize(int pid)
349{
350 int r;
351 if (!use_seize)
352 return ptrace(PTRACE_ATTACH, pid, 0, 0);
353 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
354 if (r)
355 return r;
356 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
357 return r;
358}
359#else
360# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
361#endif
362
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200363static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364set_cloexec_flag(int fd)
365{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200366 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000367
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200368 flags = fcntl(fd, F_GETFD);
369 if (flags < 0) {
370 /* Can happen only if fd is bad.
371 * Should never happen: if it does, we have a bug
372 * in the caller. Therefore we just abort
373 * instead of propagating the error.
374 */
375 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376 }
377
378 newflags = flags | FD_CLOEXEC;
379 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200380 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000381
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200382 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000383}
384
385/*
386 * When strace is setuid executable, we have to swap uids
387 * before and after filesystem and process management operations.
388 */
389static void
390swap_uid(void)
391{
392#ifndef SVR4
393 int euid = geteuid(), uid = getuid();
394
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200395 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200396 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397 }
398#endif
399}
400
Roland McGrath4bfa6262007-07-05 20:03:16 +0000401#if _LFS64_LARGEFILE
402# define fopen_for_output fopen64
403#else
404# define fopen_for_output fopen
405#endif
406
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000407static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200408strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000409{
410 FILE *fp;
411
412 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200413 fp = fopen_for_output(path, "w");
414 if (!fp)
415 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000416 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200417 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000418 return fp;
419}
420
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200421static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000422
423#ifndef _PATH_BSHELL
424# define _PATH_BSHELL "/bin/sh"
425#endif
426
427/*
428 * We cannot use standard popen(3) here because we have to distinguish
429 * popen child process from other processes we trace, and standard popen(3)
430 * does not export its child's pid.
431 */
432static FILE *
433strace_popen(const char *command)
434{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200435 FILE *fp;
436 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000437
438 swap_uid();
439 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200440 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000441
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200442 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000443
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200444 popen_pid = vfork();
445 if (popen_pid == -1)
446 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000447
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200448 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000449 /* child */
450 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200451 if (fds[0] != 0) {
452 if (dup2(fds[0], 0))
453 perror_msg_and_die("dup2");
454 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000455 }
456 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200457 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000458 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200459
460 /* parent */
461 close(fds[0]);
462 swap_uid();
463 fp = fdopen(fds[1], "w");
464 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200465 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200466 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000467}
468
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200469static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000470newoutf(struct tcb *tcp)
471{
472 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000473 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000474 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200475 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000476 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000477}
478
Roland McGrath02203312007-06-11 22:06:31 +0000479static void
480startup_attach(void)
481{
482 int tcbi;
483 struct tcb *tcp;
484
485 /*
486 * Block user interruptions as we would leave the traced
487 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200488 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200489 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000490 */
491 if (interactive)
492 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
493
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000494 if (daemonized_tracer) {
495 pid_t pid = fork();
496 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200497 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000498 }
499 if (pid) { /* parent */
500 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200501 * Wait for grandchild to attach to straced process
502 * (grandparent). Grandchild SIGKILLs us after it attached.
503 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000504 * it proceeds to exec the straced program.
505 */
506 pause();
507 _exit(0); /* paranoia */
508 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200509 /* grandchild */
510 /* We will be the tracer process. Remember our new pid: */
511 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000512 }
513
Roland McGrath02203312007-06-11 22:06:31 +0000514 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
515 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200516
Denys Vlasenkod116a732011-09-05 14:01:33 +0200517 /* Is this a process we should attach to, but not yet attached? */
518 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
519 continue; /* no */
520
521 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000522 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200523 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000524
525#ifdef USE_PROCFS
526 if (proc_open(tcp, 1) < 0) {
527 fprintf(stderr, "trouble opening proc file\n");
528 droptcb(tcp);
529 continue;
530 }
531#else /* !USE_PROCFS */
532# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000533 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000534 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000535 DIR *dir;
536
537 sprintf(procdir, "/proc/%d/task", tcp->pid);
538 dir = opendir(procdir);
539 if (dir != NULL) {
540 unsigned int ntid = 0, nerr = 0;
541 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200542
Roland McGrath02203312007-06-11 22:06:31 +0000543 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200544 struct tcb *cur_tcp;
545 int tid;
546
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000547 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000548 continue;
549 tid = atoi(de->d_name);
550 if (tid <= 0)
551 continue;
552 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100553 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000554 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200555 if (debug)
556 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200557 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200558 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200559 if (debug)
560 fprintf(stderr, "attach to pid %d succeeded\n", tid);
561 cur_tcp = tcp;
562 if (tid != tcp->pid)
563 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100564 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000565 }
566 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200567 if (interactive) {
568 sigprocmask(SIG_SETMASK, &empty_set, NULL);
569 if (interrupted)
570 goto ret;
571 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
572 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000573 ntid -= nerr;
574 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000575 perror("attach: ptrace(PTRACE_ATTACH, ...)");
576 droptcb(tcp);
577 continue;
578 }
579 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000580 fprintf(stderr, ntid > 1
581? "Process %u attached with %u threads - interrupt to quit\n"
582: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200583 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000584 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200585 if (!(tcp->flags & TCB_STARTUP)) {
586 /* -p PID, we failed to attach to PID itself
587 * but did attach to some of its sibling threads.
588 * Drop PID's tcp.
589 */
590 droptcb(tcp);
591 }
Roland McGrath02203312007-06-11 22:06:31 +0000592 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000593 } /* if (opendir worked) */
594 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200595# endif /* LINUX */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100596 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000597 perror("attach: ptrace(PTRACE_ATTACH, ...)");
598 droptcb(tcp);
599 continue;
600 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100601 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200602 if (debug)
603 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000604
605 if (daemonized_tracer) {
606 /*
607 * It is our grandparent we trace, not a -p PID.
608 * Don't want to just detach on exit, so...
609 */
610 tcp->flags &= ~TCB_ATTACHED;
611 /*
612 * Make parent go away.
613 * Also makes grandparent's wait() unblock.
614 */
615 kill(getppid(), SIGKILL);
616 }
617
Roland McGrath02203312007-06-11 22:06:31 +0000618#endif /* !USE_PROCFS */
619 if (!qflag)
620 fprintf(stderr,
621 "Process %u attached - interrupt to quit\n",
622 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200623 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000624
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200625 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000626 if (interactive)
627 sigprocmask(SIG_SETMASK, &empty_set, NULL);
628}
629
630static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200631startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000632{
633 struct stat statbuf;
634 const char *filename;
635 char pathname[MAXPATHLEN];
636 int pid = 0;
637 struct tcb *tcp;
638
639 filename = argv[0];
640 if (strchr(filename, '/')) {
641 if (strlen(filename) > sizeof pathname - 1) {
642 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200643 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000644 }
645 strcpy(pathname, filename);
646 }
647#ifdef USE_DEBUGGING_EXEC
648 /*
649 * Debuggers customarily check the current directory
650 * first regardless of the path but doing that gives
651 * security geeks a panic attack.
652 */
653 else if (stat(filename, &statbuf) == 0)
654 strcpy(pathname, filename);
655#endif /* USE_DEBUGGING_EXEC */
656 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000657 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000658 int m, n, len;
659
660 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100661 const char *colon = strchr(path, ':');
662 if (colon) {
663 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000664 m = n + 1;
665 }
666 else
667 m = n = strlen(path);
668 if (n == 0) {
669 if (!getcwd(pathname, MAXPATHLEN))
670 continue;
671 len = strlen(pathname);
672 }
673 else if (n > sizeof pathname - 1)
674 continue;
675 else {
676 strncpy(pathname, path, n);
677 len = n;
678 }
679 if (len && pathname[len - 1] != '/')
680 pathname[len++] = '/';
681 strcpy(pathname + len, filename);
682 if (stat(pathname, &statbuf) == 0 &&
683 /* Accept only regular files
684 with some execute bits set.
685 XXX not perfect, might still fail */
686 S_ISREG(statbuf.st_mode) &&
687 (statbuf.st_mode & 0111))
688 break;
689 }
690 }
691 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200692 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000693 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000694 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000695 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200696 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000697 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200698 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
699 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000700 ) {
701 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200702 if (outf != stderr)
703 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000704#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200705# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000706 /* Kludge for SGI, see proc_open for details. */
707 sa.sa_handler = foobar;
708 sa.sa_flags = 0;
709 sigemptyset(&sa.sa_mask);
710 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200711# endif
712# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000713 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200714# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200715 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200716# endif
Roland McGrath02203312007-06-11 22:06:31 +0000717#else /* !USE_PROCFS */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100718 if (!daemonized_tracer && !use_seize) {
719 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200720 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000721 }
Roland McGrath02203312007-06-11 22:06:31 +0000722 }
Roland McGrath02203312007-06-11 22:06:31 +0000723
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200724 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000725 uid_t run_euid = run_uid;
726 gid_t run_egid = run_gid;
727
728 if (statbuf.st_mode & S_ISUID)
729 run_euid = statbuf.st_uid;
730 if (statbuf.st_mode & S_ISGID)
731 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000732 /*
733 * It is important to set groups before we
734 * lose privileges on setuid.
735 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200736 if (initgroups(username, run_gid) < 0) {
737 perror_msg_and_die("initgroups");
738 }
739 if (setregid(run_gid, run_egid) < 0) {
740 perror_msg_and_die("setregid");
741 }
742 if (setreuid(run_uid, run_euid) < 0) {
743 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000744 }
745 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200746 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000747 setreuid(run_uid, run_uid);
748
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000749 if (!daemonized_tracer) {
750 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200751 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000752 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200753 * the immediately following execve syscall.
754 * Can't do this on NOMMU systems, we are after
755 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000756 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400757 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200758 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000759 } else {
760 struct sigaction sv_sigchld;
761 sigaction(SIGCHLD, NULL, &sv_sigchld);
762 /*
763 * Make sure it is not SIG_IGN, otherwise wait
764 * will not block.
765 */
766 signal(SIGCHLD, SIG_DFL);
767 /*
768 * Wait for grandchild to attach to us.
769 * It kills child after that, and wait() unblocks.
770 */
771 alarm(3);
772 wait(NULL);
773 alarm(0);
774 sigaction(SIGCHLD, &sv_sigchld, NULL);
775 }
Roland McGrath02203312007-06-11 22:06:31 +0000776#endif /* !USE_PROCFS */
777
778 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200779 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000780 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000781
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200782 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200783
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200784 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100785 if (!use_seize) {
786 /* child did PTRACE_TRACEME, nothing to do in parent */
787 } else {
788 if (!strace_vforked) {
789 /* Wait until child stopped itself */
790 int status;
791 while (waitpid(pid, &status, WSTOPPED) < 0) {
792 if (errno == EINTR)
793 continue;
794 perror_msg_and_die("waitpid");
795 }
796 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
797 kill(pid, SIGKILL);
798 perror_msg_and_die("Unexpected wait status %x", status);
799 }
800 }
801 /* Else: vforked case, we have no way to sync.
802 * Just attach to it as soon as possible.
803 * This means that we may miss a few first syscalls...
804 */
805
806 if (ptrace_attach_or_seize(pid)) {
807 kill(pid, SIGKILL);
808 perror_msg_and_die("Can't attach to %d", pid);
809 }
810 if (!strace_vforked)
811 kill(pid, SIGCONT);
812 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200813 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200814 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100815 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200816 else
817 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200818 }
819 else {
820 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
821 strace_tracer_pid = getpid();
822 /* The tracee is our parent: */
823 pid = getppid();
824 tcp = alloctcb(pid);
825 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000826 tcp->flags |= TCB_ATTACHED;
827 }
Roland McGrath02203312007-06-11 22:06:31 +0000828#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000829 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200830 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000831 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200832#endif
Roland McGrath02203312007-06-11 22:06:31 +0000833}
834
Wang Chaob13c0de2010-11-12 17:25:19 +0800835#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000836static void kill_save_errno(pid_t pid, int sig)
837{
838 int saved_errno = errno;
839
840 (void) kill(pid, sig);
841 errno = saved_errno;
842}
843
Wang Chaob13c0de2010-11-12 17:25:19 +0800844/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000845 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800846 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000847 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800848 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000849static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200850test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800851{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000852 int pid, expected_grandchild = 0, found_grandchild = 0;
853 const unsigned int test_options = PTRACE_O_TRACECLONE |
854 PTRACE_O_TRACEFORK |
855 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800856
Denys Vlasenko5d645812011-08-20 12:48:18 +0200857 pid = fork();
858 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000859 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200860 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000861 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100862 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000863 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
864 __func__);
865 kill(pid, SIGSTOP);
866 if (fork() < 0)
867 perror_msg_and_die("fork");
868 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800869 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000870
871 while (1) {
872 int status, tracee_pid;
873
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000874 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000875 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000876 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000877 if (errno == EINTR)
878 continue;
879 else if (errno == ECHILD)
880 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000881 kill_save_errno(pid, SIGKILL);
882 perror_msg_and_die("%s: unexpected wait result %d",
883 __func__, tracee_pid);
884 }
885 if (WIFEXITED(status)) {
886 if (WEXITSTATUS(status)) {
887 if (tracee_pid != pid)
888 kill_save_errno(pid, SIGKILL);
889 error_msg_and_die("%s: unexpected exit status %u",
890 __func__, WEXITSTATUS(status));
891 }
892 continue;
893 }
894 if (WIFSIGNALED(status)) {
895 if (tracee_pid != pid)
896 kill_save_errno(pid, SIGKILL);
897 error_msg_and_die("%s: unexpected signal %u",
898 __func__, WTERMSIG(status));
899 }
900 if (!WIFSTOPPED(status)) {
901 if (tracee_pid != pid)
902 kill_save_errno(tracee_pid, SIGKILL);
903 kill(pid, SIGKILL);
904 error_msg_and_die("%s: unexpected wait status %x",
905 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000906 }
907 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000908 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000909 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
910 kill_save_errno(tracee_pid, SIGKILL);
911 kill_save_errno(pid, SIGKILL);
912 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800913 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000914 continue;
915 }
916 switch (WSTOPSIG(status)) {
917 case SIGSTOP:
918 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
919 && errno != EINVAL && errno != EIO)
920 perror_msg("PTRACE_SETOPTIONS");
921 break;
922 case SIGTRAP:
923 if (status >> 16 == PTRACE_EVENT_FORK) {
924 long msg = 0;
925
926 if (ptrace(PTRACE_GETEVENTMSG, pid,
927 NULL, (long) &msg) == 0)
928 expected_grandchild = msg;
929 }
930 break;
931 }
932 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
933 kill_save_errno(pid, SIGKILL);
934 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800935 }
936 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000937 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200938 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000939 if (debug)
940 fprintf(stderr, "ptrace_setoptions = %#x\n",
941 ptrace_setoptions);
942 return;
943 }
944 error_msg("Test for PTRACE_O_TRACECLONE failed, "
945 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800946}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200947
948/*
949 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
950 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
951 * and then see whether it will stop with (SIGTRAP | 0x80).
952 *
953 * Use of this option enables correct handling of user-generated SIGTRAPs,
954 * and SIGTRAPs generated by special instructions such as int3 on x86:
955 * _start: .globl _start
956 * int3
957 * movl $42, %ebx
958 * movl $1, %eax
959 * int $0x80
960 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
961 */
962static void
963test_ptrace_setoptions_for_all(void)
964{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000965 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
966 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200967 int pid;
968 int it_worked = 0;
969
970 pid = fork();
971 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200972 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200973
974 if (pid == 0) {
975 pid = getpid();
976 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200977 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000978 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
979 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200980 kill(pid, SIGSTOP);
981 _exit(0); /* parent should see entry into this syscall */
982 }
983
984 while (1) {
985 int status, tracee_pid;
986
987 errno = 0;
988 tracee_pid = wait(&status);
989 if (tracee_pid <= 0) {
990 if (errno == EINTR)
991 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000992 kill_save_errno(pid, SIGKILL);
993 perror_msg_and_die("%s: unexpected wait result %d",
994 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200995 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200996 if (WIFEXITED(status)) {
997 if (WEXITSTATUS(status) == 0)
998 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000999 error_msg_and_die("%s: unexpected exit status %u",
1000 __func__, WEXITSTATUS(status));
1001 }
1002 if (WIFSIGNALED(status)) {
1003 error_msg_and_die("%s: unexpected signal %u",
1004 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001005 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001006 if (!WIFSTOPPED(status)) {
1007 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001008 error_msg_and_die("%s: unexpected wait status %x",
1009 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001010 }
1011 if (WSTOPSIG(status) == SIGSTOP) {
1012 /*
1013 * We don't check "options aren't accepted" error.
1014 * If it happens, we'll never get (SIGTRAP | 0x80),
1015 * and thus will decide to not use the option.
1016 * IOW: the outcome of the test will be correct.
1017 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001018 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1019 && errno != EINVAL && errno != EIO)
1020 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001021 }
1022 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1023 it_worked = 1;
1024 }
1025 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001026 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001027 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001028 }
1029 }
1030
1031 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001032 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001033 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001034 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001035 fprintf(stderr, "ptrace_setoptions = %#x\n",
1036 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001037 return;
1038 }
1039
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001040 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1041 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001042}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001043
1044# ifdef USE_SEIZE
1045static void
1046test_ptrace_seize(void)
1047{
1048 int pid;
1049
1050 pid = fork();
1051 if (pid < 0)
1052 perror_msg_and_die("fork");
1053
1054 if (pid == 0) {
1055 pause();
1056 _exit(0);
1057 }
1058
1059 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1060 * attaching tracee continues to run unless a trap condition occurs.
1061 * PTRACE_SEIZE doesn't affect signal or group stop state.
1062 */
1063 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1064 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1065 } else if (debug) {
1066 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1067 }
1068
1069 kill(pid, SIGKILL);
1070
1071 while (1) {
1072 int status, tracee_pid;
1073
1074 errno = 0;
1075 tracee_pid = waitpid(pid, &status, 0);
1076 if (tracee_pid <= 0) {
1077 if (errno == EINTR)
1078 continue;
1079 perror_msg_and_die("%s: unexpected wait result %d",
1080 __func__, tracee_pid);
1081 }
1082 if (WIFSIGNALED(status)) {
1083 return;
1084 }
1085 error_msg_and_die("%s: unexpected wait status %x",
1086 __func__, status);
1087 }
1088}
1089# else /* !USE_SEIZE */
1090# define test_ptrace_seize() ((void)0)
1091# endif
1092
Wang Chaob13c0de2010-11-12 17:25:19 +08001093#endif
1094
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001095/* Noinline: don't want main to have struct utsname permanently on stack */
1096static void __attribute__ ((noinline))
1097get_os_release(void)
1098{
1099 struct utsname u;
1100 if (uname(&u) < 0)
1101 perror_msg_and_die("uname");
1102 os_release = strdup(u.release);
1103 if (!os_release)
1104 die_out_of_memory();
1105}
1106
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001108main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 struct tcb *tcp;
1111 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001112 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 struct sigaction sa;
1114
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001115 progname = argv[0] ? argv[0] : "strace";
1116
Denys Vlasenko75422762011-05-27 14:36:01 +02001117 strace_tracer_pid = getpid();
1118
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001119 get_os_release();
1120
Roland McGrathee9d4352002-12-18 04:16:10 +00001121 /* Allocate the initial tcbtab. */
1122 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001123 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001124 if (!tcbtab)
1125 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001126 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001127 if (!tcp)
1128 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001129 for (c = 0; c < tcbtabsize; c++)
1130 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001131
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001133 set_sortby(DEFAULT_SORTBY);
1134 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 qualify("trace=all");
1136 qualify("abbrev=all");
1137 qualify("verbose=all");
1138 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001140 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001141#ifndef USE_PROCFS
1142 "D"
1143#endif
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001144 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145 switch (c) {
1146 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001147 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001148 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001149 }
1150 cflag = CFLAG_ONLY_STATS;
1151 break;
1152 case 'C':
1153 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001154 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001155 }
1156 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 break;
1158 case 'd':
1159 debug++;
1160 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001161#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001162 case 'D':
1163 daemonized_tracer = 1;
1164 break;
1165#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001166 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001167 optF = 1;
1168 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 case 'f':
1170 followfork++;
1171 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 case 'h':
1173 usage(stdout, 0);
1174 break;
1175 case 'i':
1176 iflag++;
1177 break;
1178 case 'q':
1179 qflag++;
1180 break;
1181 case 'r':
1182 rflag++;
1183 tflag++;
1184 break;
1185 case 't':
1186 tflag++;
1187 break;
1188 case 'T':
1189 dtime++;
1190 break;
1191 case 'x':
1192 xflag++;
1193 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001194 case 'y':
1195 show_fd_path = 1;
1196 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001197 case 'v':
1198 qualify("abbrev=none");
1199 break;
1200 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001201 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 exit(0);
1203 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001204 case 'z':
1205 not_failing_only = 1;
1206 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 case 'a':
1208 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001209 if (acolumn < 0)
1210 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 break;
1212 case 'e':
1213 qualify(optarg);
1214 break;
1215 case 'o':
1216 outfname = strdup(optarg);
1217 break;
1218 case 'O':
1219 set_overhead(atoi(optarg));
1220 break;
1221 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001222 pid = atoi(optarg);
1223 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001224 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225 break;
1226 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001227 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001228 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 break;
1230 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001231 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232 tcp->flags |= TCB_ATTACHED;
1233 pflag_seen++;
1234 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001235 case 'P':
1236 tracing_paths = 1;
1237 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001238 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001239 }
1240 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 case 's':
1242 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001243 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001244 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001245 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001246 break;
1247 case 'S':
1248 set_sortby(optarg);
1249 break;
1250 case 'u':
1251 username = strdup(optarg);
1252 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001253 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001254 if (putenv(optarg) < 0)
1255 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001256 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001257 case 'I':
1258 opt_intr = atoi(optarg);
1259 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1260 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1261 }
1262 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263 default:
1264 usage(stderr, 1);
1265 break;
1266 }
1267 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001268 argv += optind;
1269 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270
Denys Vlasenko102ec492011-08-25 01:27:59 +02001271 acolumn_spaces = malloc(acolumn + 1);
1272 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001273 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001274 memset(acolumn_spaces, ' ', acolumn);
1275 acolumn_spaces[acolumn] = '\0';
1276
Denys Vlasenko837399a2012-01-24 11:37:03 +01001277 /* Must have PROG [ARGS], or -p PID. Not both. */
1278 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001279 usage(stderr, 1);
1280
Wang Chaod322a4b2010-08-05 14:30:11 +08001281 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001282 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001283 }
1284
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001285 if (!followfork)
1286 followfork = optF;
1287
Roland McGrathcb9def62006-04-25 07:48:03 +00001288 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001289 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001290 }
1291
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 /* See if they want to run as another user. */
1293 if (username != NULL) {
1294 struct passwd *pent;
1295
1296 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001297 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001299 pent = getpwnam(username);
1300 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001301 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 }
1303 run_uid = pent->pw_uid;
1304 run_gid = pent->pw_gid;
1305 }
1306 else {
1307 run_uid = getuid();
1308 run_gid = getgid();
1309 }
1310
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001311#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001312 if (followfork)
1313 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001314 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001315 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001316#endif
1317
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318 /* Check if they want to redirect the output. */
1319 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001320 /* See if they want to pipe the output. */
1321 if (outfname[0] == '|' || outfname[0] == '!') {
1322 /*
1323 * We can't do the <outfname>.PID funny business
1324 * when using popen, so prohibit it.
1325 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001326 if (followfork > 1)
1327 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1328 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001329 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001330 else if (followfork <= 1)
1331 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332 }
1333
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001334 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001335 char *buf = malloc(BUFSIZ);
1336 if (!buf)
1337 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001338 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001339 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001340 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001341 if (!opt_intr)
1342 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001343 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001344 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001345 if (!opt_intr)
1346 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001347
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001348 /* argv[0] -pPID -oFILE Default interactive setting
1349 * yes 0 0 INTR_WHILE_WAIT
1350 * no 1 0 INTR_WHILE_WAIT
1351 * yes 0 1 INTR_NEVER
1352 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001353 */
1354
1355 /* STARTUP_CHILD must be called before the signal handlers get
1356 installed below as they are inherited into the spawned process.
1357 Also we do not need to be protected by them as during interruption
1358 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001359 if (argv[0])
1360 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001361
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362 sigemptyset(&empty_set);
1363 sigemptyset(&blocked_set);
1364 sa.sa_handler = SIG_IGN;
1365 sigemptyset(&sa.sa_mask);
1366 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001367 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1368 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1369 if (opt_intr != INTR_ANYWHERE) {
1370 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1371 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1372 /*
1373 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1374 * fatal signals are blocked while syscall stop is processed,
1375 * and acted on in between, when waiting for new syscall stops.
1376 * In non-interactive mode, signals are ignored.
1377 */
1378 if (opt_intr == INTR_WHILE_WAIT) {
1379 sigaddset(&blocked_set, SIGHUP);
1380 sigaddset(&blocked_set, SIGINT);
1381 sigaddset(&blocked_set, SIGQUIT);
1382 sigaddset(&blocked_set, SIGPIPE);
1383 sigaddset(&blocked_set, SIGTERM);
1384 sa.sa_handler = interrupt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385#ifdef SUNOS4
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001386 /* POSIX signals on sunos4.1 are a little broken. */
1387 sa.sa_flags = SA_INTERRUPT;
1388#endif
1389 }
1390 /* SIG_IGN, or set handler for these */
1391 sigaction(SIGHUP, &sa, NULL);
1392 sigaction(SIGINT, &sa, NULL);
1393 sigaction(SIGQUIT, &sa, NULL);
1394 sigaction(SIGPIPE, &sa, NULL);
1395 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001397#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 sa.sa_handler = reaper;
1399 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001400#else
1401 /* Make sure SIGCHLD has the default action so that waitpid
1402 definitely works without losing track of children. The user
1403 should not have given us a bogus state to inherit, but he might
1404 have. Arguably we should detect SIG_IGN here and pass it on
1405 to children, but probably noone really needs that. */
1406 sa.sa_handler = SIG_DFL;
1407 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001408#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001409
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001410 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001411 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001412
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413 if (trace() < 0)
1414 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001415
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001417 fflush(NULL);
1418 if (exit_code > 0xff) {
1419 /* Child was killed by a signal, mimic that. */
1420 exit_code &= 0xff;
1421 signal(exit_code, SIG_DFL);
1422 raise(exit_code);
1423 /* Paranoia - what if this signal is not fatal?
1424 Exit with 128 + signo then. */
1425 exit_code += 128;
1426 }
1427 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428}
1429
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001430static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001431expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001432{
1433 /* Allocate some more TCBs and expand the table.
1434 We don't want to relocate the TCBs because our
1435 callers have pointers and it would be a pain.
1436 So tcbtab is a table of pointers. Since we never
1437 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001438 int i = tcbtabsize;
1439 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1440 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001441 if (!newtab || !newtcbs)
1442 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001443 tcbtabsize *= 2;
1444 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001445 while (i < tcbtabsize)
1446 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001447}
1448
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001450alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451{
1452 int i;
1453 struct tcb *tcp;
1454
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001455 if (nprocs == tcbtabsize)
1456 expand_tcbtab();
1457
Roland McGrathee9d4352002-12-18 04:16:10 +00001458 for (i = 0; i < tcbtabsize; i++) {
1459 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001461 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001463 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001465#if SUPPORTED_PERSONALITIES > 1
1466 tcp->currpers = current_personality;
1467#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001468#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001470#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001472 if (debug)
1473 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001474 if (command_options_parsed)
1475 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 return tcp;
1477 }
1478 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001479 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480}
1481
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001482#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001484proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485{
1486 char proc[32];
1487 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001488#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001489 int i;
1490 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 sigset_t signals;
1492 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001493#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494#ifndef HAVE_POLLABLE_PROCFS
1495 static int last_pfd;
1496#endif
1497
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001498#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001499 /* Open the process pseudo-files in /proc. */
1500 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001501 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1502 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 perror("strace: open(\"/proc/...\", ...)");
1504 return -1;
1505 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001506 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001507 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001508 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1509 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001510 perror("strace: open(\"/proc/...\", ...)");
1511 return -1;
1512 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001513 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001514 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001515 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1516 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001517 perror("strace: open(\"/proc/...\", ...)");
1518 return -1;
1519 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001520 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001521#else
1522 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001523# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001524 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001525 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001526# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001527 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001528 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001529# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001530 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001531 perror("strace: open(\"/proc/...\", ...)");
1532 return -1;
1533 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001534 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001535#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001536#ifdef FREEBSD
1537 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001538 tcp->pfd_reg = open(proc, O_RDONLY);
1539 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001540 perror("strace: open(\"/proc/.../regs\", ...)");
1541 return -1;
1542 }
1543 if (cflag) {
1544 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001545 tcp->pfd_status = open(proc, O_RDONLY);
1546 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001547 perror("strace: open(\"/proc/.../status\", ...)");
1548 return -1;
1549 }
1550 } else
1551 tcp->pfd_status = -1;
1552#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001553 rebuild_pollv();
1554 if (!attaching) {
1555 /*
1556 * Wait for the child to pause. Because of a race
1557 * condition we have to poll for the event.
1558 */
1559 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001560 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001561 perror("strace: PIOCSTATUS");
1562 return -1;
1563 }
1564 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001565 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001566 }
1567 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001568#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001569 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001570 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001571 perror("strace: PIOCSTOP");
1572 return -1;
1573 }
Roland McGrath553a6092002-12-16 20:40:39 +00001574#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575#ifdef PIOCSET
1576 /* Set Run-on-Last-Close. */
1577 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001578 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579 perror("PIOCSET PR_RLC");
1580 return -1;
1581 }
1582 /* Set or Reset Inherit-on-Fork. */
1583 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001584 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585 perror("PIOC{SET,RESET} PR_FORK");
1586 return -1;
1587 }
1588#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001589#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1591 perror("PIOCSRLC");
1592 return -1;
1593 }
1594 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1595 perror("PIOC{S,R}FORK");
1596 return -1;
1597 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001598#else /* FREEBSD */
1599 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1600 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1601 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001602 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001603 }
1604 arg &= ~PF_LINGER;
1605 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001606 perror("PIOCSFL");
1607 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001608 }
1609#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001611#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001612 /* Enable all syscall entries we care about. */
1613 premptyset(&syscalls);
1614 for (i = 1; i < MAX_QUALS; ++i) {
1615 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001616 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001617 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001618 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001619 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001620 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001621#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001622 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001623#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001624#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001625 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001626#endif
1627#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001628 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001629#endif
1630#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001631 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001632#endif
1633 }
1634 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 perror("PIOCSENTRY");
1636 return -1;
1637 }
John Hughes19e49982001-10-19 08:59:12 +00001638 /* Enable the syscall exits. */
1639 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640 perror("PIOSEXIT");
1641 return -1;
1642 }
John Hughes19e49982001-10-19 08:59:12 +00001643 /* Enable signals we care about. */
1644 premptyset(&signals);
1645 for (i = 1; i < MAX_QUALS; ++i) {
1646 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001647 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001648 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001649 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650 perror("PIOCSTRACE");
1651 return -1;
1652 }
John Hughes19e49982001-10-19 08:59:12 +00001653 /* Enable faults we care about */
1654 premptyset(&faults);
1655 for (i = 1; i < MAX_QUALS; ++i) {
1656 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001657 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001658 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001659 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660 perror("PIOCSFAULT");
1661 return -1;
1662 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001663#else /* FREEBSD */
1664 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001665 arg = S_SIG | S_SCE | S_SCX;
1666 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001667 perror("PIOCBIS");
1668 return -1;
1669 }
1670#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671 if (!attaching) {
1672#ifdef MIPS
1673 /*
1674 * The SGI PRSABORT doesn't work for pause() so
1675 * we send it a caught signal to wake it up.
1676 */
1677 kill(tcp->pid, SIGINT);
1678#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001679#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001681 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001682 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 perror("PIOCRUN");
1684 return -1;
1685 }
Roland McGrath553a6092002-12-16 20:40:39 +00001686#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001687#endif /* !MIPS*/
1688#ifdef FREEBSD
1689 /* wake up the child if it received the SIGSTOP */
1690 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001691#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692 for (;;) {
1693 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001694 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001695 perror("PIOCWSTOP");
1696 return -1;
1697 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001698 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001699 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001700 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001701 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 break;
1703 }
1704 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001705#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001706 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001707 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1708#else
1709 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1710#endif
1711 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 perror("PIOCRUN");
1713 return -1;
1714 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001715#ifdef FREEBSD
1716 /* handle the case where we "opened" the child before
1717 it did the kill -STOP */
1718 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1719 tcp->status.PR_WHAT == SIGSTOP)
1720 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001721#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722 }
1723 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001724#ifdef FREEBSD
1725 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001726 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001727 /* We are attaching to an already running process.
1728 * Try to figure out the state of the process in syscalls,
1729 * to handle the first event well.
1730 * This is done by having a look at the "wchan" property of the
1731 * process, which tells where it is stopped (if it is). */
1732 FILE * status;
1733 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001734
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001735 sprintf(proc, "/proc/%d/status", tcp->pid);
1736 status = fopen(proc, "r");
1737 if (status &&
1738 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1739 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1740 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1741 strcmp(wchan, "stopevent")) {
1742 /* The process is asleep in the middle of a syscall.
1743 Fake the syscall entry event */
1744 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1745 tcp->status.PR_WHY = PR_SYSENTRY;
1746 trace_syscall(tcp);
1747 }
1748 if (status)
1749 fclose(status);
1750 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001751 }
1752#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753#ifndef HAVE_POLLABLE_PROCFS
1754 if (proc_poll_pipe[0] != -1)
1755 proc_poller(tcp->pfd);
1756 else if (nprocs > 1) {
1757 proc_poll_open();
1758 proc_poller(last_pfd);
1759 proc_poller(tcp->pfd);
1760 }
1761 last_pfd = tcp->pfd;
1762#endif /* !HAVE_POLLABLE_PROCFS */
1763 return 0;
1764}
1765
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001766#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001768static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001769pid2tcb(int pid)
1770{
1771 int i;
1772
1773 if (pid <= 0)
1774 return NULL;
1775
1776 for (i = 0; i < tcbtabsize; i++) {
1777 struct tcb *tcp = tcbtab[i];
1778 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1779 return tcp;
1780 }
1781
1782 return NULL;
1783}
1784
1785#ifdef USE_PROCFS
1786
1787static struct tcb *
1788first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789{
1790 int i;
1791 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001792 for (i = 0; i < tcbtabsize; i++) {
1793 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 if (tcp->flags & TCB_INUSE)
1795 return tcp;
1796 }
1797 return NULL;
1798}
1799
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001801pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802{
1803 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804
Roland McGrathca16be82003-01-10 19:55:28 +00001805 for (i = 0; i < tcbtabsize; i++) {
1806 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807 if (tcp->pfd != pfd)
1808 continue;
1809 if (tcp->flags & TCB_INUSE)
1810 return tcp;
1811 }
1812 return NULL;
1813}
1814
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001815#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816
1817void
Denys Vlasenko12014262011-05-30 14:00:14 +02001818droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819{
1820 if (tcp->pid == 0)
1821 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001822
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001824 if (debug)
1825 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001826
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001827#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828 if (tcp->pfd != -1) {
1829 close(tcp->pfd);
1830 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001831# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001832 if (tcp->pfd_reg != -1) {
1833 close(tcp->pfd_reg);
1834 tcp->pfd_reg = -1;
1835 }
1836 if (tcp->pfd_status != -1) {
1837 close(tcp->pfd_status);
1838 tcp->pfd_status = -1;
1839 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001840# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001841 tcp->flags = 0; /* rebuild_pollv needs it */
1842 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001844#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001845
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001846 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001848
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001849 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001850}
1851
Roland McGrath0a463882007-07-05 18:43:16 +00001852/* detach traced process; continue with sig
1853 Never call DETACH twice on the same process as both unattached and
1854 attached-unstopped processes give the same ESRCH. For unattached process we
1855 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856
1857static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001858detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859{
1860 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001861#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001862 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001863#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864
1865 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001866 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001867
1868#ifdef LINUX
1869 /*
1870 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001871 * before detaching. Arghh. We go through hoops
1872 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001874#if defined(SPARC)
1875#undef PTRACE_DETACH
1876#define PTRACE_DETACH PTRACE_SUNDETACH
1877#endif
Roland McGrath02203312007-06-11 22:06:31 +00001878 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001879 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001880 * We must catch exactly one as otherwise the detached process
1881 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001882 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001883 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001884 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001885 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001887 }
1888 else if (errno != ESRCH) {
1889 /* Shouldn't happen. */
1890 perror("detach: ptrace(PTRACE_DETACH, ...)");
1891 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001892 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001893 if (errno != ESRCH)
1894 perror("detach: checking sanity");
1895 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001896 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001897 if (errno != ESRCH)
1898 perror("detach: stopping child");
1899 }
Roland McGrath02203312007-06-11 22:06:31 +00001900 else
1901 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001902 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001904#ifdef __WALL
1905 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1906 if (errno == ECHILD) /* Already gone. */
1907 break;
1908 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001909 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001910 break;
1911 }
1912#endif /* __WALL */
1913 /* No __WALL here. */
1914 if (waitpid(tcp->pid, &status, 0) < 0) {
1915 if (errno != ECHILD) {
1916 perror("detach: waiting");
1917 break;
1918 }
1919#ifdef __WCLONE
1920 /* If no processes, try clones. */
1921 if (wait4(tcp->pid, &status, __WCLONE,
1922 NULL) < 0) {
1923 if (errno != ECHILD)
1924 perror("detach: waiting");
1925 break;
1926 }
1927#endif /* __WCLONE */
1928 }
1929#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001930 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001931#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932 if (!WIFSTOPPED(status)) {
1933 /* Au revoir, mon ami. */
1934 break;
1935 }
1936 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001937 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 break;
1939 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001940 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001941 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001942 : WSTOPSIG(status));
1943 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001944 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001946 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001947#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948
1949#if defined(SUNOS4)
1950 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001951 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952#endif /* SUNOS4 */
1953
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001954 if (!qflag)
1955 fprintf(stderr, "Process %u detached\n", tcp->pid);
1956
1957 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001958
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959 return error;
1960}
1961
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001962#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001963
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001964static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965{
1966 int pid;
1967 int status;
1968
1969 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970 }
1971}
1972
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001973#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001974
1975static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001976cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001977{
1978 int i;
1979 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001980 int fatal_sig;
1981
1982 /* 'interrupted' is a volatile object, fetch it only once */
1983 fatal_sig = interrupted;
1984 if (!fatal_sig)
1985 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986
Roland McGrathee9d4352002-12-18 04:16:10 +00001987 for (i = 0; i < tcbtabsize; i++) {
1988 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989 if (!(tcp->flags & TCB_INUSE))
1990 continue;
1991 if (debug)
1992 fprintf(stderr,
1993 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001994 if (printing_tcp &&
1995 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1996 tprints(" <unfinished ...>\n");
1997 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 }
1999 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01002000 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 else {
2002 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01002003 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004 }
2005 }
2006 if (cflag)
2007 call_summary(outf);
2008}
2009
2010static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002011interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01002013 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002014}
2015
2016#ifndef HAVE_STRERROR
2017
Roland McGrath6d2b3492002-12-30 00:51:30 +00002018#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002019extern int sys_nerr;
2020extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00002021#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002022
2023const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002024strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025{
2026 static char buf[64];
2027
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002028 if (err_no < 1 || err_no >= sys_nerr) {
2029 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002030 return buf;
2031 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02002032 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033}
2034
2035#endif /* HAVE_STERRROR */
2036
2037#ifndef HAVE_STRSIGNAL
2038
Roland McGrath8f474e02003-01-14 07:53:33 +00002039#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00002040extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00002042#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
2043extern char *_sys_siglist[];
2044#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045
2046const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002047strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048{
2049 static char buf[64];
2050
2051 if (sig < 1 || sig >= NSIG) {
2052 sprintf(buf, "Unknown signal %d", sig);
2053 return buf;
2054 }
2055#ifdef HAVE__SYS_SIGLIST
2056 return _sys_siglist[sig];
2057#else
2058 return sys_siglist[sig];
2059#endif
2060}
2061
2062#endif /* HAVE_STRSIGNAL */
2063
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002064#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065
2066static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002067rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068{
2069 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02002071 free(pollv);
2072 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02002073 if (!pollv)
2074 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00002075
Roland McGrathca16be82003-01-10 19:55:28 +00002076 for (i = j = 0; i < tcbtabsize; i++) {
2077 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 if (!(tcp->flags & TCB_INUSE))
2079 continue;
2080 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002081 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002082 j++;
2083 }
2084 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002085 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002086 }
2087}
2088
2089#ifndef HAVE_POLLABLE_PROCFS
2090
2091static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002092proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002093{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002094 int i;
2095
2096 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002097 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002098 }
2099 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02002100 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 }
2102}
2103
2104static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002105proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106{
2107 int i;
2108 int n;
2109 struct proc_pollfd pollinfo;
2110
Denys Vlasenko5d645812011-08-20 12:48:18 +02002111 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
2112 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113 return n;
2114 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002115 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 }
2117 for (i = 0; i < nprocs; i++) {
2118 if (pollv[i].fd == pollinfo.fd)
2119 pollv[i].revents = pollinfo.revents;
2120 else
2121 pollv[i].revents = 0;
2122 }
2123 poller_pid = pollinfo.pid;
2124 return 1;
2125}
2126
2127static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002128wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129{
2130}
2131
2132static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002133proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134{
2135 struct proc_pollfd pollinfo;
2136 struct sigaction sa;
2137 sigset_t blocked_set, empty_set;
2138 int i;
2139 int n;
2140 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002141#ifdef FREEBSD
2142 struct procfs_status pfs;
2143#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002144
2145 switch (fork()) {
2146 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002147 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 case 0:
2149 break;
2150 default:
2151 return;
2152 }
2153
2154 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2155 sa.sa_flags = 0;
2156 sigemptyset(&sa.sa_mask);
2157 sigaction(SIGHUP, &sa, NULL);
2158 sigaction(SIGINT, &sa, NULL);
2159 sigaction(SIGQUIT, &sa, NULL);
2160 sigaction(SIGPIPE, &sa, NULL);
2161 sigaction(SIGTERM, &sa, NULL);
2162 sa.sa_handler = wakeup_handler;
2163 sigaction(SIGUSR1, &sa, NULL);
2164 sigemptyset(&blocked_set);
2165 sigaddset(&blocked_set, SIGUSR1);
2166 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2167 sigemptyset(&empty_set);
2168
2169 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002170 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 }
2172 n = rl.rlim_cur;
2173 for (i = 0; i < n; i++) {
2174 if (i != pfd && i != proc_poll_pipe[1])
2175 close(i);
2176 }
2177
2178 pollinfo.fd = pfd;
2179 pollinfo.pid = getpid();
2180 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002181#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002182 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2183#else
2184 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2185#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002186 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 switch (errno) {
2188 case EINTR:
2189 continue;
2190 case EBADF:
2191 pollinfo.revents = POLLERR;
2192 break;
2193 case ENOENT:
2194 pollinfo.revents = POLLHUP;
2195 break;
2196 default:
2197 perror("proc_poller: PIOCWSTOP");
2198 }
2199 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2200 _exit(0);
2201 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002202 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2204 sigsuspend(&empty_set);
2205 }
2206}
2207
2208#endif /* !HAVE_POLLABLE_PROCFS */
2209
2210static int
2211choose_pfd()
2212{
2213 int i, j;
2214 struct tcb *tcp;
2215
2216 static int last;
2217
2218 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002219 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002220 /*
2221 * The previous process is ready to run again. We'll
2222 * let it do so if it is currently in a syscall. This
2223 * heuristic improves the readability of the trace.
2224 */
2225 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002226 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 return pollv[last].fd;
2228 }
2229
2230 for (i = 0; i < nprocs; i++) {
2231 /* Let competing children run round robin. */
2232 j = (i + last + 1) % nprocs;
2233 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2234 tcp = pfd2tcb(pollv[j].fd);
2235 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002236 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237 }
2238 droptcb(tcp);
2239 return -1;
2240 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002241 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002242 last = j;
2243 return pollv[j].fd;
2244 }
2245 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002246 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002247}
2248
2249static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002250trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002251{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002252#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002253 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002254#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002255 struct tcb *tcp;
2256 int pfd;
2257 int what;
2258 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002259 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002260
2261 for (;;) {
2262 if (interactive)
2263 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2264
2265 if (nprocs == 0)
2266 break;
2267
2268 switch (nprocs) {
2269 case 1:
2270#ifndef HAVE_POLLABLE_PROCFS
2271 if (proc_poll_pipe[0] == -1) {
2272#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002273 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274 if (!tcp)
2275 continue;
2276 pfd = tcp->pfd;
2277 if (pfd == -1)
2278 continue;
2279 break;
2280#ifndef HAVE_POLLABLE_PROCFS
2281 }
2282 /* fall through ... */
2283#endif /* !HAVE_POLLABLE_PROCFS */
2284 default:
2285#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002286#ifdef POLL_HACK
2287 /* On some systems (e.g. UnixWare) we get too much ugly
2288 "unfinished..." stuff when multiple proceses are in
2289 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002290
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002291 if (in_syscall) {
2292 struct pollfd pv;
2293 tcp = in_syscall;
2294 in_syscall = NULL;
2295 pv.fd = tcp->pfd;
2296 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002297 what = poll(&pv, 1, 1);
2298 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002299 if (interrupted)
2300 return 0;
2301 continue;
2302 }
2303 else if (what == 1 && pv.revents & POLLWANT) {
2304 goto FOUND;
2305 }
2306 }
2307#endif
2308
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002309 if (poll(pollv, nprocs, INFTIM) < 0) {
2310 if (interrupted)
2311 return 0;
2312 continue;
2313 }
2314#else /* !HAVE_POLLABLE_PROCFS */
2315 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2316 if (interrupted)
2317 return 0;
2318 continue;
2319 }
2320#endif /* !HAVE_POLLABLE_PROCFS */
2321 pfd = choose_pfd();
2322 if (pfd == -1)
2323 continue;
2324 break;
2325 }
2326
2327 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002328 tcp = pfd2tcb(pfd);
2329 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002330 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002331 }
John Hughesb6643082002-05-23 11:02:22 +00002332#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002333 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002334#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002335 /* Get the status of the process. */
2336 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002337#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002338 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002339#else /* FREEBSD */
2340 /* Thanks to some scheduling mystery, the first poller
2341 sometimes waits for the already processed end of fork
2342 event. Doing a non blocking poll here solves the problem. */
2343 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002344 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002345 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002346 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002347#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348 ioctl_errno = errno;
2349#ifndef HAVE_POLLABLE_PROCFS
2350 if (proc_poll_pipe[0] != -1) {
2351 if (ioctl_result < 0)
2352 kill(poller_pid, SIGKILL);
2353 else
2354 kill(poller_pid, SIGUSR1);
2355 }
2356#endif /* !HAVE_POLLABLE_PROCFS */
2357 }
2358 if (interrupted)
2359 return 0;
2360
2361 if (interactive)
2362 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2363
2364 if (ioctl_result < 0) {
2365 /* Find out what happened if it failed. */
2366 switch (ioctl_errno) {
2367 case EINTR:
2368 case EBADF:
2369 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002370#ifdef FREEBSD
2371 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002372#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002373 case ENOENT:
2374 droptcb(tcp);
2375 continue;
2376 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002377 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378 }
2379 }
2380
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002381#ifdef FREEBSD
2382 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2383 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002384 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002385 continue;
2386 }
Roland McGrath553a6092002-12-16 20:40:39 +00002387#endif
2388
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002389 /* clear the just started flag */
2390 tcp->flags &= ~TCB_STARTUP;
2391
2392 /* set current output file */
2393 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002394 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002395
2396 if (cflag) {
2397 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002398#ifdef FREEBSD
2399 char buf[1024];
2400 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002401
Denys Vlasenko5d645812011-08-20 12:48:18 +02002402 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2403 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002404 buf[len] = '\0';
2405 sscanf(buf,
2406 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2407 &stime.tv_sec, &stime.tv_usec);
2408 } else
2409 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002410#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2412 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002413#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002414 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2415 tcp->stime = stime;
2416 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002417 what = tcp->status.PR_WHAT;
2418 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002419#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002420 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002421 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2422 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002423 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002424 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002425 }
2426 }
2427 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002428#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002429 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002430#ifdef POLL_HACK
2431 in_syscall = tcp;
2432#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002433 case PR_SYSEXIT:
2434 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002435 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002436 }
2437 break;
2438 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002439 if (cflag != CFLAG_ONLY_STATS
2440 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002441 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002442 tprintf("--- %s (%s) ---\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002443 signame(what), strsignal(what));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002444 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002445#ifdef PR_INFO
2446 if (tcp->status.PR_INFO.si_signo == what) {
2447 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002448 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002449 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002450 tprints("\n");
2451 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002452 }
2453#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 }
2455 break;
2456 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002457 if (cflag != CFLAGS_ONLY_STATS
2458 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002459 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002460 tprintf("=== FAULT %d ===\n", what);
2461 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002462 }
2463 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002464#ifdef FREEBSD
2465 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002466 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002467#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002468 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002469 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470 break;
2471 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002472 /* Remember current print column before continuing. */
2473 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002474 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002475#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002476 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002477#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002478 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002479#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002480 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002481 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002482 }
2483 }
2484 return 0;
2485}
2486
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002487#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488
Roland McGratheb9e2e82009-06-02 16:49:22 -07002489static int
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002490trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002491{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002492#ifdef LINUX
2493 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002494 struct rusage *rup = cflag ? &ru : NULL;
2495# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002496 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002497# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002498#endif /* LINUX */
2499
Roland McGratheb9e2e82009-06-02 16:49:22 -07002500 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002501 int pid;
2502 int wait_errno;
2503 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002504 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002505 struct tcb *tcp;
2506 unsigned event;
2507
Denys Vlasenko222713a2009-03-17 14:29:59 +00002508 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002509 return 0;
2510 if (interactive)
2511 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002512#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002513# ifdef __WALL
2514 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002515 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002516 /* this kernel does not support __WALL */
2517 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002518 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002519 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002520 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002521 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002522 pid = wait4(-1, &status, __WCLONE, rup);
2523 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002524 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002525 }
2526 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002527# else
2528 pid = wait4(-1, &status, 0, rup);
2529# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002530#endif /* LINUX */
2531#ifdef SUNOS4
2532 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002533#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002535 if (interactive)
2536 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002538 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002539 switch (wait_errno) {
2540 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002541 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002542 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 /*
2544 * We would like to verify this case
2545 * but sometimes a race in Solbourne's
2546 * version of SunOS sometimes reports
2547 * ECHILD before sending us SIGCHILD.
2548 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002549 return 0;
2550 default:
2551 errno = wait_errno;
2552 perror("strace: wait");
2553 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002554 }
2555 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002556 if (pid == popen_pid) {
2557 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002558 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002559 continue;
2560 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002561
2562 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002563 if (debug) {
2564 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2565#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002566 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002567 static const char *const event_names[] = {
2568 [PTRACE_EVENT_CLONE] = "CLONE",
2569 [PTRACE_EVENT_FORK] = "FORK",
2570 [PTRACE_EVENT_VFORK] = "VFORK",
2571 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2572 [PTRACE_EVENT_EXEC] = "EXEC",
2573 [PTRACE_EVENT_EXIT] = "EXIT",
2574 };
2575 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002576 if (event < ARRAY_SIZE(event_names))
2577 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002578 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002579 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002580 e = buf;
2581 }
2582 fprintf(stderr, " PTRACE_EVENT_%s", e);
2583 }
2584#endif
2585 strcpy(buf, "???");
2586 if (WIFSIGNALED(status))
2587#ifdef WCOREDUMP
2588 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2589 WCOREDUMP(status) ? "core," : "",
2590 signame(WTERMSIG(status)));
2591#else
2592 sprintf(buf, "WIFSIGNALED,sig=%s",
2593 signame(WTERMSIG(status)));
2594#endif
2595 if (WIFEXITED(status))
2596 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2597 if (WIFSTOPPED(status))
2598 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002599#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002600 if (WIFCONTINUED(status))
2601 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002602#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002603 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2604 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002606 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002607 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002608
2609#ifdef LINUX
2610 /* Under Linux, execve changes pid to thread leader's pid,
2611 * and we see this changed pid on EVENT_EXEC and later,
2612 * execve sysexit. Leader "disappears" without exit
2613 * notification. Let user know that, drop leader's tcb,
2614 * and fix up pid in execve thread's tcb.
2615 * Effectively, execve thread's tcb replaces leader's tcb.
2616 *
2617 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2618 * on exit syscall) in multithreaded programs exactly
2619 * in order to handle this case.
2620 *
2621 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2622 * On 2.6 and earlier, it can return garbage.
2623 */
2624 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2625 long old_pid = 0;
2626 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2627 && old_pid > 0
2628 && old_pid != pid
2629 ) {
2630 struct tcb *execve_thread = pid2tcb(old_pid);
2631 if (tcp) {
2632 outf = tcp->outf;
2633 curcol = tcp->curcol;
2634 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002635 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002636 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002637 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002638 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2639 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002640 fflush(outf);
2641 }
2642 if (execve_thread) {
2643 /* swap output FILEs (needed for -ff) */
2644 tcp->outf = execve_thread->outf;
2645 execve_thread->outf = outf;
2646 }
2647 droptcb(tcp);
2648 }
2649 tcp = execve_thread;
2650 if (tcp) {
2651 tcp->pid = pid;
2652 tcp->flags |= TCB_REPRINT;
2653 }
2654 }
2655 }
2656#endif
2657
Denys Vlasenko5d645812011-08-20 12:48:18 +02002658 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002659#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002660 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002661 /* This is needed to go with the CLONE_PTRACE
2662 changes in process.c/util.c: we might see
2663 the child's initial trap before we see the
2664 parent return from the clone syscall.
2665 Leave the child suspended until the parent
2666 returns from its system call. Only then
2667 will we have the association of parent and
2668 child so that we know how to do clearbpt
2669 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002670 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002671 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002672 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002673 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002674 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002675 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002676 else
2677 /* This can happen if a clone call used
2678 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002679#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002680 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002681 if (WIFSTOPPED(status))
2682 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002683 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002684 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002685 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002686 /* set current output file */
2687 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002688 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002689#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002690 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2692 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002693 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002694#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002695
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002697 if (pid == strace_child)
2698 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002699 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002700 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2701 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002702#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002703 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002704 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002705 WCOREDUMP(status) ? "(core dumped) " : "");
2706#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002707 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002708 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002709#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01002710 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002712 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002713 droptcb(tcp);
2714 continue;
2715 }
2716 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002717 if (pid == strace_child)
2718 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002719 if (tcp == printing_tcp) {
2720 tprints(" <unfinished ...>\n");
2721 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00002722 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002723 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2724 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002725 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2726 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002727 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002728 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002729 droptcb(tcp);
2730 continue;
2731 }
2732 if (!WIFSTOPPED(status)) {
2733 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2734 droptcb(tcp);
2735 continue;
2736 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002737
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002738 /* Is this the very first time we see this tracee stopped? */
2739 if (tcp->flags & TCB_STARTUP) {
2740 if (debug)
2741 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002742 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002743 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002744 /*
2745 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002746 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002747 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002748 if (clearbpt(tcp) < 0) {
2749 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002750 droptcb(tcp);
2751 cleanup();
2752 return -1;
2753 }
2754 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002755#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002756 if (ptrace_setoptions) {
2757 if (debug)
2758 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2759 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2760 if (errno != ESRCH) {
2761 /* Should never happen, really */
2762 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002763 }
2764 }
2765 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002766#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002767 }
2768
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002769 sig = WSTOPSIG(status);
2770
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002771 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002772 /* Ptrace event */
2773#ifdef USE_SEIZE
2774 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002775 /*
2776 * PTRACE_INTERRUPT-stop or group-stop.
2777 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2778 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002779 if (sig == SIGSTOP
2780 || sig == SIGTSTP
2781 || sig == SIGTTIN
2782 || sig == SIGTTOU
2783 ) {
2784 stopped = 1;
2785 goto show_stopsig;
2786 }
2787 }
2788#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002789 goto restart_tracee_with_sig_0;
2790 }
2791
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002792 /* Is this post-attach SIGSTOP?
2793 * Interestingly, the process may stop
2794 * with STOPSIG equal to some other signal
2795 * than SIGSTOP if we happend to attach
2796 * just before the process takes a signal.
2797 */
2798 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2799 if (debug)
2800 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2801 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002802 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002803 }
2804
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002805 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002806 siginfo_t si;
2807
2808 /* Nonzero (true) if tracee is stopped by signal
2809 * (as opposed to "tracee received signal").
2810 */
2811 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002812#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002813 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002814#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002815 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002816 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002817#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002818 long pc = 0;
2819 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002820
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002821 upeek(tcp, PT_CR_IPSR, &psr);
2822 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002823
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002824# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002825 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002826# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002827# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002828#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002829# define PC_FORMAT_STR ""
2830# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002831#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002832 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002833 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002834 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002835 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002836 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002837 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002838 PC_FORMAT_ARG);
2839 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002840 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002841 strsignal(sig),
2842 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002843 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002844 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002845 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002846 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002847
2848 if (!stopped)
2849 /* It's signal-delivery-stop. Inject the signal */
2850 goto restart_tracee;
2851
2852 /* It's group-stop */
2853#ifdef USE_SEIZE
2854 if (use_seize) {
2855 /*
2856 * This ends ptrace-stop, but does *not* end group-stop.
2857 * This makes stopping signals work properly on straced process
2858 * (that is, process really stops. It used to continue to run).
2859 */
2860 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2861 cleanup();
2862 return -1;
2863 }
2864 continue;
2865 }
2866 /* We don't have PTRACE_LISTEN support... */
2867#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002868 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002869 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002870
2871 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002872 if (interrupted)
2873 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002874
2875 /* This should be syscall entry or exit.
2876 * (Or it still can be that pesky post-execve SIGTRAP!)
2877 * Handle it.
2878 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002879 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2880 /* ptrace() failed in trace_syscall() with ESRCH.
2881 * Likely a result of process disappearing mid-flight.
2882 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002883 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002884 */
2885 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002886 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002887 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002888 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002889 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002890 printing_tcp->flags |= TCB_REPRINT;
2891 tprints(" <unfinished ...>\n");
2892 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002893 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002894 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002895 /* We assume that ptrace error was caused by process death.
2896 * We used to detach(tcp) here, but since we no longer
2897 * implement "detach before death" policy/hack,
2898 * we can let this process to report its death to us
2899 * normally, via WIFEXITED or WIFSIGNALED wait status.
2900 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002901 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002902 /* It's our real child (and we also trace it) */
2903 /* my_tkill(pid, SIGKILL); - why? */
2904 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002905 }
2906 continue;
2907 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002908 restart_tracee_with_sig_0:
2909 sig = 0;
2910 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002911 /* Remember current print column before continuing. */
2912 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002913 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002914 cleanup();
2915 return -1;
2916 }
2917 }
2918 return 0;
2919}
2920
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002921#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002922
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002923void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002924tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002925{
2926 va_list args;
2927
Andreas Schwabe5355de2009-10-27 16:56:43 +01002928 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002929 if (outf) {
2930 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002931 if (n < 0) {
2932 if (outf != stderr)
2933 perror(outfname == NULL
2934 ? "<writing to pipe>" : outfname);
2935 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002936 curcol += n;
2937 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002938 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002939}
2940
2941void
2942tprints(const char *str)
2943{
2944 if (outf) {
2945 int n = fputs(str, outf);
2946 if (n >= 0) {
2947 curcol += strlen(str);
2948 return;
2949 }
2950 if (outf != stderr)
2951 perror(outfname == NULL
2952 ? "<writing to pipe>" : outfname);
2953 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002954}
2955
2956void
Denys Vlasenko12014262011-05-30 14:00:14 +02002957printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002958{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002959 if (printing_tcp) {
2960 if (printing_tcp->ptrace_errno) {
2961 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002962 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002963 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002964 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002965 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002966 printing_tcp->ptrace_errno = 0;
2967 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2968 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002969 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002970 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002971 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002972
2973 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002974 curcol = 0;
2975 if ((followfork == 1 || pflag_seen > 1) && outfname)
2976 tprintf("%-5d ", tcp->pid);
2977 else if (nprocs > 1 && !outfname)
2978 tprintf("[pid %5u] ", tcp->pid);
2979 if (tflag) {
2980 char str[sizeof("HH:MM:SS")];
2981 struct timeval tv, dtv;
2982 static struct timeval otv;
2983
2984 gettimeofday(&tv, NULL);
2985 if (rflag) {
2986 if (otv.tv_sec == 0)
2987 otv = tv;
2988 tv_sub(&dtv, &tv, &otv);
2989 tprintf("%6ld.%06ld ",
2990 (long) dtv.tv_sec, (long) dtv.tv_usec);
2991 otv = tv;
2992 }
2993 else if (tflag > 2) {
2994 tprintf("%ld.%06ld ",
2995 (long) tv.tv_sec, (long) tv.tv_usec);
2996 }
2997 else {
2998 time_t local = tv.tv_sec;
2999 strftime(str, sizeof(str), "%T", localtime(&local));
3000 if (tflag > 1)
3001 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
3002 else
3003 tprintf("%s ", str);
3004 }
3005 }
3006 if (iflag)
3007 printcall(tcp);
3008}
3009
3010void
Denys Vlasenko102ec492011-08-25 01:27:59 +02003011tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003012{
Denys Vlasenko102ec492011-08-25 01:27:59 +02003013 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02003014 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00003015}
3016
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00003017#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003018
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003019int
3020mp_ioctl(int fd, int cmd, void *arg, int size)
3021{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003022 struct iovec iov[2];
3023 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00003024
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003025 iov[0].iov_base = &cmd;
3026 iov[0].iov_len = sizeof cmd;
3027 if (arg) {
3028 ++n;
3029 iov[1].iov_base = arg;
3030 iov[1].iov_len = size;
3031 }
Roland McGrath553a6092002-12-16 20:40:39 +00003032
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00003033 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00003034}
3035
3036#endif