blob: 9c633887265228a6c6c0f00783dba7b5c99e2367 [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>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020051# if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000053# else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020058# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000059# endif
60#endif
61
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062#if defined(IA64) && defined(LINUX)
63# include <asm/ptrace_offsets.h>
64#endif
65
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000066#ifdef USE_PROCFS
67#include <poll.h>
68#endif
69
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#ifdef SVR4
71#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000072#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000073#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000074#include <sys/uio.h>
75#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000077#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000078extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000079extern int optind;
80extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082
Roland McGrath41c48222008-07-18 00:25:10 +000083int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020084unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020085/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020086static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000087int dtime = 0, xflag = 0, qflag = 0;
88cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000089static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000090/*
91 * daemonized_tracer supports -D option.
92 * With this option, strace forks twice.
93 * Unlike normal case, with -D *grandparent* process exec's,
94 * becoming a traced process. Child exits (this prevents traced process
95 * from having children it doesn't expect to have), and grandchild
96 * attaches to grandparent similarly to strace -p PID.
97 * This allows for more transparent interaction in cases
98 * when process and its parent are communicating via signals,
99 * wait() etc. Without -D, strace process gets lodged in between,
100 * disrupting parent<->child link.
101 */
102static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000104/* Sometimes we want to print only succeeding syscalls. */
105int not_failing_only = 0;
106
Grant Edwards8a082772011-04-07 20:25:40 +0000107/* Show path associated with fd arguments */
108int show_fd_path = 0;
109
110/* are we filtering traces based on paths? */
111int tracing_paths = 0;
112
Dmitry V. Levina6809652008-11-10 17:14:58 +0000113static int exit_code = 0;
114static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200115static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700116
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000117static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200118static uid_t run_uid;
119static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200122static int acolumn = DEFAULT_ACOLUMN;
123static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000124static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200125static FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100126static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200128static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200129static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
Andreas Schwabe5355de2009-10-27 16:56:43 +0100131static int detach(struct tcb *tcp, int sig);
132static int trace(void);
133static void cleanup(void);
134static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135static sigset_t empty_set, blocked_set;
136
137#ifdef HAVE_SIG_ATOMIC_T
138static volatile sig_atomic_t interrupted;
139#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141#endif /* !HAVE_SIG_ATOMIC_T */
142
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000143#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144
Andreas Schwabe5355de2009-10-27 16:56:43 +0100145static struct tcb *pfd2tcb(int pfd);
146static void reaper(int sig);
147static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000148static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149
150#ifndef HAVE_POLLABLE_PROCFS
151
Andreas Schwabe5355de2009-10-27 16:56:43 +0100152static void proc_poll_open(void);
153static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
155struct proc_pollfd {
156 int fd;
157 int revents;
158 int pid;
159};
160
161static int poller_pid;
162static int proc_poll_pipe[2] = { -1, -1 };
163
164#endif /* !HAVE_POLLABLE_PROCFS */
165
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000166#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000167#define POLLWANT POLLWRNORM
168#else
169#define POLLWANT POLLPRI
170#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000171#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172
173static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200174usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175{
176 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000177usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000178 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000179 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200180 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000181 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200183-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-f -- follow forks, -ff -- with output into separate files\n\
185-F -- attempt to follow vforks, -h -- print help message\n\
186-i -- print instruction pointer at time of syscall\n\
187-q -- suppress messages about attaching, detaching, etc.\n\
188-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
189-T -- print time spent in each syscall, -V -- print version\n\
190-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
191-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000192-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193-a column -- alignment COLUMN for printing syscall results (default %d)\n\
194-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
195 options: trace, abbrev, verbose, raw, signal, read, or write\n\
196-o file -- send trace output to FILE instead of stderr\n\
197-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
198-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000199-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
201-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
202-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000203-E var=val -- put var=val in the environment for command\n\
204-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000205-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000206" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000207-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208 */
209, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210 exit(exitval);
211}
212
Denys Vlasenko75422762011-05-27 14:36:01 +0200213static void die(void) __attribute__ ((noreturn));
214static void die(void)
215{
216 if (strace_tracer_pid == getpid()) {
217 cflag = 0;
218 cleanup();
219 }
220 exit(1);
221}
222
223static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200224{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000225 fflush(NULL);
226 fprintf(stderr, "%s: ", progname);
227 vfprintf(stderr, fmt, p);
228 if (err_no)
229 fprintf(stderr, ": %s\n", strerror(err_no));
230 else
231 putc('\n', stderr);
232 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200233}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200234
Denys Vlasenko75422762011-05-27 14:36:01 +0200235void error_msg(const char *fmt, ...)
236{
237 va_list p;
238 va_start(p, fmt);
239 verror_msg(0, fmt, p);
240 va_end(p);
241}
242
243void error_msg_and_die(const char *fmt, ...)
244{
245 va_list p;
246 va_start(p, fmt);
247 verror_msg(0, fmt, p);
248 die();
249}
250
251void perror_msg(const char *fmt, ...)
252{
253 va_list p;
254 va_start(p, fmt);
255 verror_msg(errno, fmt, p);
256 va_end(p);
257}
258
259void perror_msg_and_die(const char *fmt, ...)
260{
261 va_list p;
262 va_start(p, fmt);
263 verror_msg(errno, fmt, p);
264 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200265}
266
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200267void die_out_of_memory(void)
268{
269 static bool recursed = 0;
270 if (recursed)
271 exit(1);
272 recursed = 1;
273 error_msg_and_die("Out of memory");
274}
275
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000276#ifdef SVR4
277#ifdef MIPS
278void
279foobar()
280{
281}
282#endif /* MIPS */
283#endif /* SVR4 */
284
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400285/* Glue for systems without a MMU that cannot provide fork() */
286#ifdef HAVE_FORK
287# define strace_vforked 0
288#else
289# define strace_vforked 1
290# define fork() vfork()
291#endif
292
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200293static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000294set_cloexec_flag(int fd)
295{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200296 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000297
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200298 flags = fcntl(fd, F_GETFD);
299 if (flags < 0) {
300 /* Can happen only if fd is bad.
301 * Should never happen: if it does, we have a bug
302 * in the caller. Therefore we just abort
303 * instead of propagating the error.
304 */
305 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000306 }
307
308 newflags = flags | FD_CLOEXEC;
309 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200310 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000311
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200312 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000313}
314
315/*
316 * When strace is setuid executable, we have to swap uids
317 * before and after filesystem and process management operations.
318 */
319static void
320swap_uid(void)
321{
322#ifndef SVR4
323 int euid = geteuid(), uid = getuid();
324
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200325 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200326 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000327 }
328#endif
329}
330
Roland McGrath4bfa6262007-07-05 20:03:16 +0000331#if _LFS64_LARGEFILE
332# define fopen_for_output fopen64
333#else
334# define fopen_for_output fopen
335#endif
336
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000337static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200338strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000339{
340 FILE *fp;
341
342 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200343 fp = fopen_for_output(path, "w");
344 if (!fp)
345 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000346 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200347 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000348 return fp;
349}
350
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200351static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000352
353#ifndef _PATH_BSHELL
354# define _PATH_BSHELL "/bin/sh"
355#endif
356
357/*
358 * We cannot use standard popen(3) here because we have to distinguish
359 * popen child process from other processes we trace, and standard popen(3)
360 * does not export its child's pid.
361 */
362static FILE *
363strace_popen(const char *command)
364{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200365 FILE *fp;
366 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000367
368 swap_uid();
369 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200370 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000371
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200372 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000373
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200374 popen_pid = vfork();
375 if (popen_pid == -1)
376 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000377
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200378 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000379 /* child */
380 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200381 if (fds[0] != 0) {
382 if (dup2(fds[0], 0))
383 perror_msg_and_die("dup2");
384 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000385 }
386 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200387 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200389
390 /* parent */
391 close(fds[0]);
392 swap_uid();
393 fp = fdopen(fds[1], "w");
394 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200395 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200396 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397}
398
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200399static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400newoutf(struct tcb *tcp)
401{
402 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000403 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000404 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200405 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000406 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000407}
408
Roland McGrath02203312007-06-11 22:06:31 +0000409static void
410startup_attach(void)
411{
412 int tcbi;
413 struct tcb *tcp;
414
415 /*
416 * Block user interruptions as we would leave the traced
417 * process stopped (process state T) if we would terminate in
418 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200419 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000420 */
421 if (interactive)
422 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
423
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000424 if (daemonized_tracer) {
425 pid_t pid = fork();
426 if (pid < 0) {
427 _exit(1);
428 }
429 if (pid) { /* parent */
430 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200431 * Wait for grandchild to attach to straced process
432 * (grandparent). Grandchild SIGKILLs us after it attached.
433 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000434 * it proceeds to exec the straced program.
435 */
436 pause();
437 _exit(0); /* paranoia */
438 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200439 /* grandchild */
440 /* We will be the tracer process. Remember our new pid: */
441 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000442 }
443
Roland McGrath02203312007-06-11 22:06:31 +0000444 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
445 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200446
Roland McGrath02203312007-06-11 22:06:31 +0000447 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
448 continue;
449#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200450 if (tcp->flags & TCB_ATTACH_DONE)
Roland McGrath02203312007-06-11 22:06:31 +0000451 continue;
452#endif
453 /* Reinitialize the output since it may have changed. */
454 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200455 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000456
457#ifdef USE_PROCFS
458 if (proc_open(tcp, 1) < 0) {
459 fprintf(stderr, "trouble opening proc file\n");
460 droptcb(tcp);
461 continue;
462 }
463#else /* !USE_PROCFS */
464# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000465 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000466 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000467 DIR *dir;
468
469 sprintf(procdir, "/proc/%d/task", tcp->pid);
470 dir = opendir(procdir);
471 if (dir != NULL) {
472 unsigned int ntid = 0, nerr = 0;
473 struct dirent *de;
474 int tid;
475 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000476 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000477 continue;
478 tid = atoi(de->d_name);
479 if (tid <= 0)
480 continue;
481 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200482 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000483 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200484 if (debug)
485 fprintf(stderr, "attach to pid %d failed\n", tid);
486 }
487 else {
488 if (debug)
489 fprintf(stderr, "attach to pid %d succeeded\n", tid);
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200490 if (tid != tcp->pid) {
491 struct tcb *new_tcp = alloctcb(tid);
492 new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200493 }
Roland McGrath02203312007-06-11 22:06:31 +0000494 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000495 if (interactive) {
496 sigprocmask(SIG_SETMASK, &empty_set, NULL);
497 if (interrupted)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200498 goto ret;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000499 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
500 }
Roland McGrath02203312007-06-11 22:06:31 +0000501 }
502 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000503 ntid -= nerr;
504 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000505 perror("attach: ptrace(PTRACE_ATTACH, ...)");
506 droptcb(tcp);
507 continue;
508 }
509 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000510 fprintf(stderr, ntid > 1
511? "Process %u attached with %u threads - interrupt to quit\n"
512: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200513 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000514 }
515 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000516 } /* if (opendir worked) */
517 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200518# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000519 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
520 perror("attach: ptrace(PTRACE_ATTACH, ...)");
521 droptcb(tcp);
522 continue;
523 }
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200524 if (debug)
525 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000526
527 if (daemonized_tracer) {
528 /*
529 * It is our grandparent we trace, not a -p PID.
530 * Don't want to just detach on exit, so...
531 */
532 tcp->flags &= ~TCB_ATTACHED;
533 /*
534 * Make parent go away.
535 * Also makes grandparent's wait() unblock.
536 */
537 kill(getppid(), SIGKILL);
538 }
539
Roland McGrath02203312007-06-11 22:06:31 +0000540#endif /* !USE_PROCFS */
541 if (!qflag)
542 fprintf(stderr,
543 "Process %u attached - interrupt to quit\n",
544 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200545 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000546
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200547 ret:
548#ifdef LINUX
549 /* TCB_ATTACH_DONE flag is used only in this function */
550 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
551 tcp = tcbtab[tcbi];
552 tcp->flags &= ~TCB_ATTACH_DONE;
553 }
554#endif
555
Roland McGrath02203312007-06-11 22:06:31 +0000556 if (interactive)
557 sigprocmask(SIG_SETMASK, &empty_set, NULL);
558}
559
560static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200561startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000562{
563 struct stat statbuf;
564 const char *filename;
565 char pathname[MAXPATHLEN];
566 int pid = 0;
567 struct tcb *tcp;
568
569 filename = argv[0];
570 if (strchr(filename, '/')) {
571 if (strlen(filename) > sizeof pathname - 1) {
572 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200573 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000574 }
575 strcpy(pathname, filename);
576 }
577#ifdef USE_DEBUGGING_EXEC
578 /*
579 * Debuggers customarily check the current directory
580 * first regardless of the path but doing that gives
581 * security geeks a panic attack.
582 */
583 else if (stat(filename, &statbuf) == 0)
584 strcpy(pathname, filename);
585#endif /* USE_DEBUGGING_EXEC */
586 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000587 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000588 int m, n, len;
589
590 for (path = getenv("PATH"); path && *path; path += m) {
591 if (strchr(path, ':')) {
592 n = strchr(path, ':') - path;
593 m = n + 1;
594 }
595 else
596 m = n = strlen(path);
597 if (n == 0) {
598 if (!getcwd(pathname, MAXPATHLEN))
599 continue;
600 len = strlen(pathname);
601 }
602 else if (n > sizeof pathname - 1)
603 continue;
604 else {
605 strncpy(pathname, path, n);
606 len = n;
607 }
608 if (len && pathname[len - 1] != '/')
609 pathname[len++] = '/';
610 strcpy(pathname + len, filename);
611 if (stat(pathname, &statbuf) == 0 &&
612 /* Accept only regular files
613 with some execute bits set.
614 XXX not perfect, might still fail */
615 S_ISREG(statbuf.st_mode) &&
616 (statbuf.st_mode & 0111))
617 break;
618 }
619 }
620 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200621 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000622 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000623 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000624 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200625 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000626 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200627 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
628 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000629 ) {
630 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000631#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200632 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000633#ifdef MIPS
634 /* Kludge for SGI, see proc_open for details. */
635 sa.sa_handler = foobar;
636 sa.sa_flags = 0;
637 sigemptyset(&sa.sa_mask);
638 sigaction(SIGINT, &sa, NULL);
639#endif /* MIPS */
640#ifndef FREEBSD
641 pause();
642#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000643 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000644#endif /* FREEBSD */
645#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200646 if (outf != stderr)
647 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000648
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000649 if (!daemonized_tracer) {
650 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200651 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000652 }
653 if (debug)
654 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000655 }
Roland McGrath02203312007-06-11 22:06:31 +0000656
657 if (username != NULL || geteuid() == 0) {
658 uid_t run_euid = run_uid;
659 gid_t run_egid = run_gid;
660
661 if (statbuf.st_mode & S_ISUID)
662 run_euid = statbuf.st_uid;
663 if (statbuf.st_mode & S_ISGID)
664 run_egid = statbuf.st_gid;
665
666 /*
667 * It is important to set groups before we
668 * lose privileges on setuid.
669 */
670 if (username != NULL) {
671 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200672 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000673 }
674 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200675 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000676 }
677 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200678 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000679 }
680 }
681 }
682 else
683 setreuid(run_uid, run_uid);
684
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000685 if (!daemonized_tracer) {
686 /*
687 * Induce an immediate stop so that the parent
688 * will resume us with PTRACE_SYSCALL and display
689 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400690 * Unless of course we're on a no-MMU system where
691 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000692 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400693 if (!strace_vforked)
694 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000695 } else {
696 struct sigaction sv_sigchld;
697 sigaction(SIGCHLD, NULL, &sv_sigchld);
698 /*
699 * Make sure it is not SIG_IGN, otherwise wait
700 * will not block.
701 */
702 signal(SIGCHLD, SIG_DFL);
703 /*
704 * Wait for grandchild to attach to us.
705 * It kills child after that, and wait() unblocks.
706 */
707 alarm(3);
708 wait(NULL);
709 alarm(0);
710 sigaction(SIGCHLD, &sv_sigchld, NULL);
711 }
Roland McGrath02203312007-06-11 22:06:31 +0000712#endif /* !USE_PROCFS */
713
714 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200715 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000716 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000717
718 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200719 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
720 strace_tracer_pid = getpid();
721
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000723 if (daemonized_tracer) {
724 /* We want subsequent startup_attach() to attach to it. */
725 tcp->flags |= TCB_ATTACHED;
726 }
Roland McGrath02203312007-06-11 22:06:31 +0000727#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000728 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200729 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000730 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000731#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000732}
733
Wang Chaob13c0de2010-11-12 17:25:19 +0800734#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000735static void kill_save_errno(pid_t pid, int sig)
736{
737 int saved_errno = errno;
738
739 (void) kill(pid, sig);
740 errno = saved_errno;
741}
742
Wang Chaob13c0de2010-11-12 17:25:19 +0800743/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000744 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800745 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000746 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800747 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000748static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200749test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800750{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000751 int pid, expected_grandchild = 0, found_grandchild = 0;
752 const unsigned int test_options = PTRACE_O_TRACECLONE |
753 PTRACE_O_TRACEFORK |
754 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800755
Denys Vlasenko5d645812011-08-20 12:48:18 +0200756 pid = fork();
757 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000758 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200759 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000760 pid = getpid();
761 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
762 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
763 __func__);
764 kill(pid, SIGSTOP);
765 if (fork() < 0)
766 perror_msg_and_die("fork");
767 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800768 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000769
770 while (1) {
771 int status, tracee_pid;
772
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000773 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000774 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000775 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000776 if (errno == EINTR)
777 continue;
778 else if (errno == ECHILD)
779 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000780 kill_save_errno(pid, SIGKILL);
781 perror_msg_and_die("%s: unexpected wait result %d",
782 __func__, tracee_pid);
783 }
784 if (WIFEXITED(status)) {
785 if (WEXITSTATUS(status)) {
786 if (tracee_pid != pid)
787 kill_save_errno(pid, SIGKILL);
788 error_msg_and_die("%s: unexpected exit status %u",
789 __func__, WEXITSTATUS(status));
790 }
791 continue;
792 }
793 if (WIFSIGNALED(status)) {
794 if (tracee_pid != pid)
795 kill_save_errno(pid, SIGKILL);
796 error_msg_and_die("%s: unexpected signal %u",
797 __func__, WTERMSIG(status));
798 }
799 if (!WIFSTOPPED(status)) {
800 if (tracee_pid != pid)
801 kill_save_errno(tracee_pid, SIGKILL);
802 kill(pid, SIGKILL);
803 error_msg_and_die("%s: unexpected wait status %x",
804 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000805 }
806 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000807 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000808 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
809 kill_save_errno(tracee_pid, SIGKILL);
810 kill_save_errno(pid, SIGKILL);
811 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800812 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000813 continue;
814 }
815 switch (WSTOPSIG(status)) {
816 case SIGSTOP:
817 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
818 && errno != EINVAL && errno != EIO)
819 perror_msg("PTRACE_SETOPTIONS");
820 break;
821 case SIGTRAP:
822 if (status >> 16 == PTRACE_EVENT_FORK) {
823 long msg = 0;
824
825 if (ptrace(PTRACE_GETEVENTMSG, pid,
826 NULL, (long) &msg) == 0)
827 expected_grandchild = msg;
828 }
829 break;
830 }
831 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
832 kill_save_errno(pid, SIGKILL);
833 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800834 }
835 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000836 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200837 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000838 if (debug)
839 fprintf(stderr, "ptrace_setoptions = %#x\n",
840 ptrace_setoptions);
841 return;
842 }
843 error_msg("Test for PTRACE_O_TRACECLONE failed, "
844 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800845}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200846
847/*
848 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
849 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
850 * and then see whether it will stop with (SIGTRAP | 0x80).
851 *
852 * Use of this option enables correct handling of user-generated SIGTRAPs,
853 * and SIGTRAPs generated by special instructions such as int3 on x86:
854 * _start: .globl _start
855 * int3
856 * movl $42, %ebx
857 * movl $1, %eax
858 * int $0x80
859 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
860 */
861static void
862test_ptrace_setoptions_for_all(void)
863{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000864 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
865 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200866 int pid;
867 int it_worked = 0;
868
869 pid = fork();
870 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200871 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200872
873 if (pid == 0) {
874 pid = getpid();
875 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200876 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000877 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
878 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200879 kill(pid, SIGSTOP);
880 _exit(0); /* parent should see entry into this syscall */
881 }
882
883 while (1) {
884 int status, tracee_pid;
885
886 errno = 0;
887 tracee_pid = wait(&status);
888 if (tracee_pid <= 0) {
889 if (errno == EINTR)
890 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000891 kill_save_errno(pid, SIGKILL);
892 perror_msg_and_die("%s: unexpected wait result %d",
893 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200894 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200895 if (WIFEXITED(status)) {
896 if (WEXITSTATUS(status) == 0)
897 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000898 error_msg_and_die("%s: unexpected exit status %u",
899 __func__, WEXITSTATUS(status));
900 }
901 if (WIFSIGNALED(status)) {
902 error_msg_and_die("%s: unexpected signal %u",
903 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200904 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200905 if (!WIFSTOPPED(status)) {
906 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000907 error_msg_and_die("%s: unexpected wait status %x",
908 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200909 }
910 if (WSTOPSIG(status) == SIGSTOP) {
911 /*
912 * We don't check "options aren't accepted" error.
913 * If it happens, we'll never get (SIGTRAP | 0x80),
914 * and thus will decide to not use the option.
915 * IOW: the outcome of the test will be correct.
916 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000917 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
918 && errno != EINVAL && errno != EIO)
919 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200920 }
921 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
922 it_worked = 1;
923 }
924 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000925 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200926 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200927 }
928 }
929
930 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200931 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200932 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200933 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200934 fprintf(stderr, "ptrace_setoptions = %#x\n",
935 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200936 return;
937 }
938
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000939 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
940 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200941}
Wang Chaob13c0de2010-11-12 17:25:19 +0800942#endif
943
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000945main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000946{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947 struct tcb *tcp;
948 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000949 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950 struct sigaction sa;
951
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000952 progname = argv[0] ? argv[0] : "strace";
953
Denys Vlasenko75422762011-05-27 14:36:01 +0200954 strace_tracer_pid = getpid();
955
Roland McGrathee9d4352002-12-18 04:16:10 +0000956 /* Allocate the initial tcbtab. */
957 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200958 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200959 if (!tcbtab)
960 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200961 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200962 if (!tcp)
963 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200964 for (c = 0; c < tcbtabsize; c++)
965 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000966
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 outf = stderr;
968 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000969 set_sortby(DEFAULT_SORTBY);
970 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 qualify("trace=all");
972 qualify("abbrev=all");
973 qualify("verbose=all");
974 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000976 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000977#ifndef USE_PROCFS
978 "D"
979#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000980 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981 switch (c) {
982 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000983 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200984 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000985 }
986 cflag = CFLAG_ONLY_STATS;
987 break;
988 case 'C':
989 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200990 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000991 }
992 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993 break;
994 case 'd':
995 debug++;
996 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000997#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000998 case 'D':
999 daemonized_tracer = 1;
1000 break;
1001#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001002 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001003 optF = 1;
1004 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 case 'f':
1006 followfork++;
1007 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 case 'h':
1009 usage(stdout, 0);
1010 break;
1011 case 'i':
1012 iflag++;
1013 break;
1014 case 'q':
1015 qflag++;
1016 break;
1017 case 'r':
1018 rflag++;
1019 tflag++;
1020 break;
1021 case 't':
1022 tflag++;
1023 break;
1024 case 'T':
1025 dtime++;
1026 break;
1027 case 'x':
1028 xflag++;
1029 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001030 case 'y':
1031 show_fd_path = 1;
1032 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 case 'v':
1034 qualify("abbrev=none");
1035 break;
1036 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001037 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 exit(0);
1039 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001040 case 'z':
1041 not_failing_only = 1;
1042 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 case 'a':
1044 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001045 if (acolumn < 0)
1046 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 break;
1048 case 'e':
1049 qualify(optarg);
1050 break;
1051 case 'o':
1052 outfname = strdup(optarg);
1053 break;
1054 case 'O':
1055 set_overhead(atoi(optarg));
1056 break;
1057 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001058 pid = atoi(optarg);
1059 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001060 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061 break;
1062 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001063 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001064 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 break;
1066 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001067 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 tcp->flags |= TCB_ATTACHED;
1069 pflag_seen++;
1070 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001071 case 'P':
1072 tracing_paths = 1;
1073 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001074 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001075 }
1076 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077 case 's':
1078 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001079 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001080 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001081 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 break;
1083 case 'S':
1084 set_sortby(optarg);
1085 break;
1086 case 'u':
1087 username = strdup(optarg);
1088 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001089 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001090 if (putenv(optarg) < 0)
1091 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001092 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093 default:
1094 usage(stderr, 1);
1095 break;
1096 }
1097 }
1098
Denys Vlasenko102ec492011-08-25 01:27:59 +02001099 acolumn_spaces = malloc(acolumn + 1);
1100 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001101 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001102 memset(acolumn_spaces, ' ', acolumn);
1103 acolumn_spaces[acolumn] = '\0';
1104
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001105 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001106 usage(stderr, 1);
1107
Wang Chaod322a4b2010-08-05 14:30:11 +08001108 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001109 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001110 }
1111
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001112 if (!followfork)
1113 followfork = optF;
1114
Roland McGrathcb9def62006-04-25 07:48:03 +00001115 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001116 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001117 }
1118
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 /* See if they want to run as another user. */
1120 if (username != NULL) {
1121 struct passwd *pent;
1122
1123 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001124 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001126 pent = getpwnam(username);
1127 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001128 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 }
1130 run_uid = pent->pw_uid;
1131 run_gid = pent->pw_gid;
1132 }
1133 else {
1134 run_uid = getuid();
1135 run_gid = getgid();
1136 }
1137
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001138#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001139 if (followfork)
1140 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001141 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001142#endif
1143
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 /* Check if they want to redirect the output. */
1145 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001146 /* See if they want to pipe the output. */
1147 if (outfname[0] == '|' || outfname[0] == '!') {
1148 /*
1149 * We can't do the <outfname>.PID funny business
1150 * when using popen, so prohibit it.
1151 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001152 if (followfork > 1)
1153 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1154 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001155 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001156 else if (followfork <= 1)
1157 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 }
1159
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001160 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1161 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001163 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001164 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001167 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001168
Roland McGrath54cc1c82007-11-03 23:34:11 +00001169 /* Valid states here:
1170 optind < argc pflag_seen outfname interactive
1171 1 0 0 1
1172 0 1 0 1
1173 1 0 1 0
1174 0 1 1 1
1175 */
1176
1177 /* STARTUP_CHILD must be called before the signal handlers get
1178 installed below as they are inherited into the spawned process.
1179 Also we do not need to be protected by them as during interruption
1180 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1181 if (!pflag_seen)
1182 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 sigemptyset(&empty_set);
1185 sigemptyset(&blocked_set);
1186 sa.sa_handler = SIG_IGN;
1187 sigemptyset(&sa.sa_mask);
1188 sa.sa_flags = 0;
1189 sigaction(SIGTTOU, &sa, NULL);
1190 sigaction(SIGTTIN, &sa, NULL);
1191 if (interactive) {
1192 sigaddset(&blocked_set, SIGHUP);
1193 sigaddset(&blocked_set, SIGINT);
1194 sigaddset(&blocked_set, SIGQUIT);
1195 sigaddset(&blocked_set, SIGPIPE);
1196 sigaddset(&blocked_set, SIGTERM);
1197 sa.sa_handler = interrupt;
1198#ifdef SUNOS4
1199 /* POSIX signals on sunos4.1 are a little broken. */
1200 sa.sa_flags = SA_INTERRUPT;
1201#endif /* SUNOS4 */
1202 }
1203 sigaction(SIGHUP, &sa, NULL);
1204 sigaction(SIGINT, &sa, NULL);
1205 sigaction(SIGQUIT, &sa, NULL);
1206 sigaction(SIGPIPE, &sa, NULL);
1207 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001208#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 sa.sa_handler = reaper;
1210 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001211#else
1212 /* Make sure SIGCHLD has the default action so that waitpid
1213 definitely works without losing track of children. The user
1214 should not have given us a bogus state to inherit, but he might
1215 have. Arguably we should detect SIG_IGN here and pass it on
1216 to children, but probably noone really needs that. */
1217 sa.sa_handler = SIG_DFL;
1218 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001219#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001221 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001222 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001223
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 if (trace() < 0)
1225 exit(1);
1226 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001227 fflush(NULL);
1228 if (exit_code > 0xff) {
1229 /* Child was killed by a signal, mimic that. */
1230 exit_code &= 0xff;
1231 signal(exit_code, SIG_DFL);
1232 raise(exit_code);
1233 /* Paranoia - what if this signal is not fatal?
1234 Exit with 128 + signo then. */
1235 exit_code += 128;
1236 }
1237 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238}
1239
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001240static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001241expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001242{
1243 /* Allocate some more TCBs and expand the table.
1244 We don't want to relocate the TCBs because our
1245 callers have pointers and it would be a pain.
1246 So tcbtab is a table of pointers. Since we never
1247 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001248 int i = tcbtabsize;
1249 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1250 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001251 if (!newtab || !newtcbs)
1252 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001253 tcbtabsize *= 2;
1254 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001255 while (i < tcbtabsize)
1256 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001257}
1258
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001259struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001260alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261{
1262 int i;
1263 struct tcb *tcp;
1264
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001265 if (nprocs == tcbtabsize)
1266 expand_tcbtab();
1267
Roland McGrathee9d4352002-12-18 04:16:10 +00001268 for (i = 0; i < tcbtabsize; i++) {
1269 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001271 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001273 tcp->flags = TCB_INUSE | TCB_STARTUP;
1274 tcp->outf = outf; /* Initialise to current out file */
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001275#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001277#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001278 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001279 if (debug)
1280 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001281 if (command_options_parsed)
1282 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283 return tcp;
1284 }
1285 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001286 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287}
1288
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001289#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001291proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292{
1293 char proc[32];
1294 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001295#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001296 int i;
1297 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298 sigset_t signals;
1299 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001300#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001301#ifndef HAVE_POLLABLE_PROCFS
1302 static int last_pfd;
1303#endif
1304
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001305#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001306 /* Open the process pseudo-files in /proc. */
1307 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001308 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1309 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310 perror("strace: open(\"/proc/...\", ...)");
1311 return -1;
1312 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001313 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001314 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001315 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1316 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001317 perror("strace: open(\"/proc/...\", ...)");
1318 return -1;
1319 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001320 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001321 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001322 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1323 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001324 perror("strace: open(\"/proc/...\", ...)");
1325 return -1;
1326 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001327 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001328#else
1329 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001330# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001331 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001332 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001333# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001334 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001335 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001336# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001337 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001338 perror("strace: open(\"/proc/...\", ...)");
1339 return -1;
1340 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001341 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001342#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001343#ifdef FREEBSD
1344 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001345 tcp->pfd_reg = open(proc, O_RDONLY);
1346 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001347 perror("strace: open(\"/proc/.../regs\", ...)");
1348 return -1;
1349 }
1350 if (cflag) {
1351 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001352 tcp->pfd_status = open(proc, O_RDONLY);
1353 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001354 perror("strace: open(\"/proc/.../status\", ...)");
1355 return -1;
1356 }
1357 } else
1358 tcp->pfd_status = -1;
1359#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001360 rebuild_pollv();
1361 if (!attaching) {
1362 /*
1363 * Wait for the child to pause. Because of a race
1364 * condition we have to poll for the event.
1365 */
1366 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001367 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001368 perror("strace: PIOCSTATUS");
1369 return -1;
1370 }
1371 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001372 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001373 }
1374 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001375#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001376 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001377 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001378 perror("strace: PIOCSTOP");
1379 return -1;
1380 }
Roland McGrath553a6092002-12-16 20:40:39 +00001381#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382#ifdef PIOCSET
1383 /* Set Run-on-Last-Close. */
1384 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001385 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 perror("PIOCSET PR_RLC");
1387 return -1;
1388 }
1389 /* Set or Reset Inherit-on-Fork. */
1390 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001391 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 perror("PIOC{SET,RESET} PR_FORK");
1393 return -1;
1394 }
1395#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001396#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001397 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1398 perror("PIOCSRLC");
1399 return -1;
1400 }
1401 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1402 perror("PIOC{S,R}FORK");
1403 return -1;
1404 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001405#else /* FREEBSD */
1406 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1407 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1408 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001409 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001410 }
1411 arg &= ~PF_LINGER;
1412 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001413 perror("PIOCSFL");
1414 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001415 }
1416#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001418#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001419 /* Enable all syscall entries we care about. */
1420 premptyset(&syscalls);
1421 for (i = 1; i < MAX_QUALS; ++i) {
1422 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001423 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001424 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001425 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001426 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001427 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001428#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001429 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001430#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001431#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001432 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001433#endif
1434#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001435 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001436#endif
1437#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001438 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001439#endif
1440 }
1441 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 perror("PIOCSENTRY");
1443 return -1;
1444 }
John Hughes19e49982001-10-19 08:59:12 +00001445 /* Enable the syscall exits. */
1446 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 perror("PIOSEXIT");
1448 return -1;
1449 }
John Hughes19e49982001-10-19 08:59:12 +00001450 /* Enable signals we care about. */
1451 premptyset(&signals);
1452 for (i = 1; i < MAX_QUALS; ++i) {
1453 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001454 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001455 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001456 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457 perror("PIOCSTRACE");
1458 return -1;
1459 }
John Hughes19e49982001-10-19 08:59:12 +00001460 /* Enable faults we care about */
1461 premptyset(&faults);
1462 for (i = 1; i < MAX_QUALS; ++i) {
1463 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001464 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001465 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001466 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467 perror("PIOCSFAULT");
1468 return -1;
1469 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001470#else /* FREEBSD */
1471 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001472 arg = S_SIG | S_SCE | S_SCX;
1473 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001474 perror("PIOCBIS");
1475 return -1;
1476 }
1477#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001478 if (!attaching) {
1479#ifdef MIPS
1480 /*
1481 * The SGI PRSABORT doesn't work for pause() so
1482 * we send it a caught signal to wake it up.
1483 */
1484 kill(tcp->pid, SIGINT);
1485#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001486#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001488 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001489 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490 perror("PIOCRUN");
1491 return -1;
1492 }
Roland McGrath553a6092002-12-16 20:40:39 +00001493#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001494#endif /* !MIPS*/
1495#ifdef FREEBSD
1496 /* wake up the child if it received the SIGSTOP */
1497 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001498#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 for (;;) {
1500 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001501 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 perror("PIOCWSTOP");
1503 return -1;
1504 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001505 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001506 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001507 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001508 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 break;
1510 }
1511 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001512#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001513 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001514 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1515#else
1516 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1517#endif
1518 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 perror("PIOCRUN");
1520 return -1;
1521 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001522#ifdef FREEBSD
1523 /* handle the case where we "opened" the child before
1524 it did the kill -STOP */
1525 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1526 tcp->status.PR_WHAT == SIGSTOP)
1527 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001528#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 }
1530 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001531#ifdef FREEBSD
1532 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001533 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001534 /* We are attaching to an already running process.
1535 * Try to figure out the state of the process in syscalls,
1536 * to handle the first event well.
1537 * This is done by having a look at the "wchan" property of the
1538 * process, which tells where it is stopped (if it is). */
1539 FILE * status;
1540 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001541
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001542 sprintf(proc, "/proc/%d/status", tcp->pid);
1543 status = fopen(proc, "r");
1544 if (status &&
1545 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1546 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1547 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1548 strcmp(wchan, "stopevent")) {
1549 /* The process is asleep in the middle of a syscall.
1550 Fake the syscall entry event */
1551 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1552 tcp->status.PR_WHY = PR_SYSENTRY;
1553 trace_syscall(tcp);
1554 }
1555 if (status)
1556 fclose(status);
1557 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001558 }
1559#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001560#ifndef HAVE_POLLABLE_PROCFS
1561 if (proc_poll_pipe[0] != -1)
1562 proc_poller(tcp->pfd);
1563 else if (nprocs > 1) {
1564 proc_poll_open();
1565 proc_poller(last_pfd);
1566 proc_poller(tcp->pfd);
1567 }
1568 last_pfd = tcp->pfd;
1569#endif /* !HAVE_POLLABLE_PROCFS */
1570 return 0;
1571}
1572
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001573#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001575struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001576pid2tcb(int pid)
1577{
1578 int i;
1579
1580 if (pid <= 0)
1581 return NULL;
1582
1583 for (i = 0; i < tcbtabsize; i++) {
1584 struct tcb *tcp = tcbtab[i];
1585 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1586 return tcp;
1587 }
1588
1589 return NULL;
1590}
1591
1592#ifdef USE_PROCFS
1593
1594static struct tcb *
1595first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596{
1597 int i;
1598 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001599 for (i = 0; i < tcbtabsize; i++) {
1600 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601 if (tcp->flags & TCB_INUSE)
1602 return tcp;
1603 }
1604 return NULL;
1605}
1606
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001608pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609{
1610 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001611
Roland McGrathca16be82003-01-10 19:55:28 +00001612 for (i = 0; i < tcbtabsize; i++) {
1613 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 if (tcp->pfd != pfd)
1615 continue;
1616 if (tcp->flags & TCB_INUSE)
1617 return tcp;
1618 }
1619 return NULL;
1620}
1621
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001622#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623
1624void
Denys Vlasenko12014262011-05-30 14:00:14 +02001625droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626{
1627 if (tcp->pid == 0)
1628 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001629
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001631 if (debug)
1632 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001633
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001634#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 if (tcp->pfd != -1) {
1636 close(tcp->pfd);
1637 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001638# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001639 if (tcp->pfd_reg != -1) {
1640 close(tcp->pfd_reg);
1641 tcp->pfd_reg = -1;
1642 }
1643 if (tcp->pfd_status != -1) {
1644 close(tcp->pfd_status);
1645 tcp->pfd_status = -1;
1646 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001647# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001648 tcp->flags = 0; /* rebuild_pollv needs it */
1649 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001651#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001652
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001653 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001655
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001656 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657}
1658
Roland McGrath0a463882007-07-05 18:43:16 +00001659/* detach traced process; continue with sig
1660 Never call DETACH twice on the same process as both unattached and
1661 attached-unstopped processes give the same ESRCH. For unattached process we
1662 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663
1664static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001665detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666{
1667 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001668#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001669 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001670#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671
1672 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001673 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674
1675#ifdef LINUX
1676 /*
1677 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001678 * before detaching. Arghh. We go through hoops
1679 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001681#if defined(SPARC)
1682#undef PTRACE_DETACH
1683#define PTRACE_DETACH PTRACE_SUNDETACH
1684#endif
Roland McGrath02203312007-06-11 22:06:31 +00001685 /*
1686 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1687 * expected SIGSTOP. We must catch exactly one as otherwise the
1688 * detached process would be left stopped (process state T).
1689 */
1690 catch_sigstop = (tcp->flags & TCB_STARTUP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001691 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1692 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001694 }
1695 else if (errno != ESRCH) {
1696 /* Shouldn't happen. */
1697 perror("detach: ptrace(PTRACE_DETACH, ...)");
1698 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001699 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001700 if (errno != ESRCH)
1701 perror("detach: checking sanity");
1702 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001703 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001704 if (errno != ESRCH)
1705 perror("detach: stopping child");
1706 }
Roland McGrath02203312007-06-11 22:06:31 +00001707 else
1708 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001709 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001711#ifdef __WALL
1712 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1713 if (errno == ECHILD) /* Already gone. */
1714 break;
1715 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001716 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001717 break;
1718 }
1719#endif /* __WALL */
1720 /* No __WALL here. */
1721 if (waitpid(tcp->pid, &status, 0) < 0) {
1722 if (errno != ECHILD) {
1723 perror("detach: waiting");
1724 break;
1725 }
1726#ifdef __WCLONE
1727 /* If no processes, try clones. */
1728 if (wait4(tcp->pid, &status, __WCLONE,
1729 NULL) < 0) {
1730 if (errno != ECHILD)
1731 perror("detach: waiting");
1732 break;
1733 }
1734#endif /* __WCLONE */
1735 }
1736#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001737 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001738#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 if (!WIFSTOPPED(status)) {
1740 /* Au revoir, mon ami. */
1741 break;
1742 }
1743 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001744 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 break;
1746 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001747 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001748 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001749 : WSTOPSIG(status));
1750 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001753 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001754#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755
1756#if defined(SUNOS4)
1757 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1758 if (sig && kill(tcp->pid, sig) < 0)
1759 perror("detach: kill");
1760 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001761 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762#endif /* SUNOS4 */
1763
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764 if (!qflag)
1765 fprintf(stderr, "Process %u detached\n", tcp->pid);
1766
1767 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001768
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769 return error;
1770}
1771
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001772#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001774static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775{
1776 int pid;
1777 int status;
1778
1779 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780 }
1781}
1782
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001783#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784
1785static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001786cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787{
1788 int i;
1789 struct tcb *tcp;
1790
Roland McGrathee9d4352002-12-18 04:16:10 +00001791 for (i = 0; i < tcbtabsize; i++) {
1792 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793 if (!(tcp->flags & TCB_INUSE))
1794 continue;
1795 if (debug)
1796 fprintf(stderr,
1797 "cleanup: looking at pid %u\n", tcp->pid);
1798 if (tcp_last &&
1799 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001800 tprintf(" <unfinished ...>");
1801 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802 }
1803 if (tcp->flags & TCB_ATTACHED)
1804 detach(tcp, 0);
1805 else {
1806 kill(tcp->pid, SIGCONT);
1807 kill(tcp->pid, SIGTERM);
1808 }
1809 }
1810 if (cflag)
1811 call_summary(outf);
1812}
1813
1814static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001815interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816{
1817 interrupted = 1;
1818}
1819
1820#ifndef HAVE_STRERROR
1821
Roland McGrath6d2b3492002-12-30 00:51:30 +00001822#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823extern int sys_nerr;
1824extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001825#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826
1827const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001828strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829{
1830 static char buf[64];
1831
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001832 if (err_no < 1 || err_no >= sys_nerr) {
1833 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834 return buf;
1835 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001836 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837}
1838
1839#endif /* HAVE_STERRROR */
1840
1841#ifndef HAVE_STRSIGNAL
1842
Roland McGrath8f474e02003-01-14 07:53:33 +00001843#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001844extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001846#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1847extern char *_sys_siglist[];
1848#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849
1850const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001851strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852{
1853 static char buf[64];
1854
1855 if (sig < 1 || sig >= NSIG) {
1856 sprintf(buf, "Unknown signal %d", sig);
1857 return buf;
1858 }
1859#ifdef HAVE__SYS_SIGLIST
1860 return _sys_siglist[sig];
1861#else
1862 return sys_siglist[sig];
1863#endif
1864}
1865
1866#endif /* HAVE_STRSIGNAL */
1867
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001868#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869
1870static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001871rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872{
1873 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001875 free(pollv);
1876 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001877 if (!pollv)
1878 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001879
Roland McGrathca16be82003-01-10 19:55:28 +00001880 for (i = j = 0; i < tcbtabsize; i++) {
1881 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882 if (!(tcp->flags & TCB_INUSE))
1883 continue;
1884 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001885 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 j++;
1887 }
1888 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001889 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890 }
1891}
1892
1893#ifndef HAVE_POLLABLE_PROCFS
1894
1895static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001896proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 int i;
1899
1900 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001901 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 }
1903 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001904 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 }
1906}
1907
1908static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001909proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910{
1911 int i;
1912 int n;
1913 struct proc_pollfd pollinfo;
1914
Denys Vlasenko5d645812011-08-20 12:48:18 +02001915 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1916 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917 return n;
1918 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001919 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001920 }
1921 for (i = 0; i < nprocs; i++) {
1922 if (pollv[i].fd == pollinfo.fd)
1923 pollv[i].revents = pollinfo.revents;
1924 else
1925 pollv[i].revents = 0;
1926 }
1927 poller_pid = pollinfo.pid;
1928 return 1;
1929}
1930
1931static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001932wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933{
1934}
1935
1936static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001937proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938{
1939 struct proc_pollfd pollinfo;
1940 struct sigaction sa;
1941 sigset_t blocked_set, empty_set;
1942 int i;
1943 int n;
1944 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001945#ifdef FREEBSD
1946 struct procfs_status pfs;
1947#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948
1949 switch (fork()) {
1950 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001951 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 case 0:
1953 break;
1954 default:
1955 return;
1956 }
1957
1958 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1959 sa.sa_flags = 0;
1960 sigemptyset(&sa.sa_mask);
1961 sigaction(SIGHUP, &sa, NULL);
1962 sigaction(SIGINT, &sa, NULL);
1963 sigaction(SIGQUIT, &sa, NULL);
1964 sigaction(SIGPIPE, &sa, NULL);
1965 sigaction(SIGTERM, &sa, NULL);
1966 sa.sa_handler = wakeup_handler;
1967 sigaction(SIGUSR1, &sa, NULL);
1968 sigemptyset(&blocked_set);
1969 sigaddset(&blocked_set, SIGUSR1);
1970 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1971 sigemptyset(&empty_set);
1972
1973 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001974 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975 }
1976 n = rl.rlim_cur;
1977 for (i = 0; i < n; i++) {
1978 if (i != pfd && i != proc_poll_pipe[1])
1979 close(i);
1980 }
1981
1982 pollinfo.fd = pfd;
1983 pollinfo.pid = getpid();
1984 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001985#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001986 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1987#else
1988 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1989#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001990 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001991 switch (errno) {
1992 case EINTR:
1993 continue;
1994 case EBADF:
1995 pollinfo.revents = POLLERR;
1996 break;
1997 case ENOENT:
1998 pollinfo.revents = POLLHUP;
1999 break;
2000 default:
2001 perror("proc_poller: PIOCWSTOP");
2002 }
2003 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2004 _exit(0);
2005 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002006 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2008 sigsuspend(&empty_set);
2009 }
2010}
2011
2012#endif /* !HAVE_POLLABLE_PROCFS */
2013
2014static int
2015choose_pfd()
2016{
2017 int i, j;
2018 struct tcb *tcp;
2019
2020 static int last;
2021
2022 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002023 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 /*
2025 * The previous process is ready to run again. We'll
2026 * let it do so if it is currently in a syscall. This
2027 * heuristic improves the readability of the trace.
2028 */
2029 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002030 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 return pollv[last].fd;
2032 }
2033
2034 for (i = 0; i < nprocs; i++) {
2035 /* Let competing children run round robin. */
2036 j = (i + last + 1) % nprocs;
2037 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2038 tcp = pfd2tcb(pollv[j].fd);
2039 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002040 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041 }
2042 droptcb(tcp);
2043 return -1;
2044 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002045 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002046 last = j;
2047 return pollv[j].fd;
2048 }
2049 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002050 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002051}
2052
2053static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002054trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002056#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002057 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002058#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059 struct tcb *tcp;
2060 int pfd;
2061 int what;
2062 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002063 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064
2065 for (;;) {
2066 if (interactive)
2067 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2068
2069 if (nprocs == 0)
2070 break;
2071
2072 switch (nprocs) {
2073 case 1:
2074#ifndef HAVE_POLLABLE_PROCFS
2075 if (proc_poll_pipe[0] == -1) {
2076#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002077 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 if (!tcp)
2079 continue;
2080 pfd = tcp->pfd;
2081 if (pfd == -1)
2082 continue;
2083 break;
2084#ifndef HAVE_POLLABLE_PROCFS
2085 }
2086 /* fall through ... */
2087#endif /* !HAVE_POLLABLE_PROCFS */
2088 default:
2089#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002090#ifdef POLL_HACK
2091 /* On some systems (e.g. UnixWare) we get too much ugly
2092 "unfinished..." stuff when multiple proceses are in
2093 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002094
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002095 if (in_syscall) {
2096 struct pollfd pv;
2097 tcp = in_syscall;
2098 in_syscall = NULL;
2099 pv.fd = tcp->pfd;
2100 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002101 what = poll(&pv, 1, 1);
2102 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002103 if (interrupted)
2104 return 0;
2105 continue;
2106 }
2107 else if (what == 1 && pv.revents & POLLWANT) {
2108 goto FOUND;
2109 }
2110 }
2111#endif
2112
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113 if (poll(pollv, nprocs, INFTIM) < 0) {
2114 if (interrupted)
2115 return 0;
2116 continue;
2117 }
2118#else /* !HAVE_POLLABLE_PROCFS */
2119 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2120 if (interrupted)
2121 return 0;
2122 continue;
2123 }
2124#endif /* !HAVE_POLLABLE_PROCFS */
2125 pfd = choose_pfd();
2126 if (pfd == -1)
2127 continue;
2128 break;
2129 }
2130
2131 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002132 tcp = pfd2tcb(pfd);
2133 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002134 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002135 }
John Hughesb6643082002-05-23 11:02:22 +00002136#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002137 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002138#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 /* Get the status of the process. */
2140 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002141#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002142 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002143#else /* FREEBSD */
2144 /* Thanks to some scheduling mystery, the first poller
2145 sometimes waits for the already processed end of fork
2146 event. Doing a non blocking poll here solves the problem. */
2147 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002148 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002149 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002150 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002151#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002152 ioctl_errno = errno;
2153#ifndef HAVE_POLLABLE_PROCFS
2154 if (proc_poll_pipe[0] != -1) {
2155 if (ioctl_result < 0)
2156 kill(poller_pid, SIGKILL);
2157 else
2158 kill(poller_pid, SIGUSR1);
2159 }
2160#endif /* !HAVE_POLLABLE_PROCFS */
2161 }
2162 if (interrupted)
2163 return 0;
2164
2165 if (interactive)
2166 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2167
2168 if (ioctl_result < 0) {
2169 /* Find out what happened if it failed. */
2170 switch (ioctl_errno) {
2171 case EINTR:
2172 case EBADF:
2173 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002174#ifdef FREEBSD
2175 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002176#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177 case ENOENT:
2178 droptcb(tcp);
2179 continue;
2180 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002181 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002182 }
2183 }
2184
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002185#ifdef FREEBSD
2186 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2187 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002188 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002189 continue;
2190 }
Roland McGrath553a6092002-12-16 20:40:39 +00002191#endif
2192
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002193 /* clear the just started flag */
2194 tcp->flags &= ~TCB_STARTUP;
2195
2196 /* set current output file */
2197 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002198 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199
2200 if (cflag) {
2201 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002202#ifdef FREEBSD
2203 char buf[1024];
2204 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002205
Denys Vlasenko5d645812011-08-20 12:48:18 +02002206 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2207 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002208 buf[len] = '\0';
2209 sscanf(buf,
2210 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2211 &stime.tv_sec, &stime.tv_usec);
2212 } else
2213 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002214#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002215 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2216 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002217#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2219 tcp->stime = stime;
2220 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002221 what = tcp->status.PR_WHAT;
2222 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002223#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002225 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2226 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002228 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 }
2230 }
2231 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002232#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002234#ifdef POLL_HACK
2235 in_syscall = tcp;
2236#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237 case PR_SYSEXIT:
2238 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002239 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002240 }
2241 break;
2242 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002243 if (cflag != CFLAG_ONLY_STATS
2244 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245 printleader(tcp);
2246 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002247 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002248 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002249#ifdef PR_INFO
2250 if (tcp->status.PR_INFO.si_signo == what) {
2251 printleader(tcp);
2252 tprintf(" siginfo=");
2253 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002254 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002255 }
2256#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 }
2258 break;
2259 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002260 if (cflag != CFLAGS_ONLY_STATS
2261 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002262 printleader(tcp);
2263 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002264 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 }
2266 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002267#ifdef FREEBSD
2268 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002269 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002270#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002271 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002272 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002273 break;
2274 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002275 /* Remember current print column before continuing. */
2276 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002277 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002278#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002279 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002280#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002281 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002282#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002283 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002284 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285 }
2286 }
2287 return 0;
2288}
2289
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002290#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002291
Roland McGratheb9e2e82009-06-02 16:49:22 -07002292static int
2293trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294{
2295 int pid;
2296 int wait_errno;
2297 int status;
2298 struct tcb *tcp;
2299#ifdef LINUX
2300 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002301 struct rusage *rup = cflag ? &ru : NULL;
2302# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002303 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002304# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305#endif /* LINUX */
2306
Roland McGratheb9e2e82009-06-02 16:49:22 -07002307 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002308 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002309 return 0;
2310 if (interactive)
2311 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002313# ifdef __WALL
2314 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002315 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002316 /* this kernel does not support __WALL */
2317 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002318 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002319 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002320 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002321 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002322 pid = wait4(-1, &status, __WCLONE, rup);
2323 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002324 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002325 }
2326 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002327# else
2328 pid = wait4(-1, &status, 0, rup);
2329# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330#endif /* LINUX */
2331#ifdef SUNOS4
2332 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002333#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002335 if (interactive)
2336 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002338 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002339 switch (wait_errno) {
2340 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002342 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343 /*
2344 * We would like to verify this case
2345 * but sometimes a race in Solbourne's
2346 * version of SunOS sometimes reports
2347 * ECHILD before sending us SIGCHILD.
2348 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002349 return 0;
2350 default:
2351 errno = wait_errno;
2352 perror("strace: wait");
2353 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002354 }
2355 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002356 if (pid == popen_pid) {
2357 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002358 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002359 continue;
2360 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002361 if (debug) {
2362 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2363#ifdef LINUX
2364 unsigned ev = (unsigned)status >> 16;
2365 if (ev) {
2366 static const char *const event_names[] = {
2367 [PTRACE_EVENT_CLONE] = "CLONE",
2368 [PTRACE_EVENT_FORK] = "FORK",
2369 [PTRACE_EVENT_VFORK] = "VFORK",
2370 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2371 [PTRACE_EVENT_EXEC] = "EXEC",
2372 [PTRACE_EVENT_EXIT] = "EXIT",
2373 };
2374 const char *e;
2375 if (ev < ARRAY_SIZE(event_names))
2376 e = event_names[ev];
2377 else {
2378 sprintf(buf, "?? (%u)", ev);
2379 e = buf;
2380 }
2381 fprintf(stderr, " PTRACE_EVENT_%s", e);
2382 }
2383#endif
2384 strcpy(buf, "???");
2385 if (WIFSIGNALED(status))
2386#ifdef WCOREDUMP
2387 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2388 WCOREDUMP(status) ? "core," : "",
2389 signame(WTERMSIG(status)));
2390#else
2391 sprintf(buf, "WIFSIGNALED,sig=%s",
2392 signame(WTERMSIG(status)));
2393#endif
2394 if (WIFEXITED(status))
2395 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2396 if (WIFSTOPPED(status))
2397 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002398#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002399 if (WIFCONTINUED(status))
2400 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002401#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002402 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2403 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002404
2405 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002406 tcp = pid2tcb(pid);
2407 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002408#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002409 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002410 /* This is needed to go with the CLONE_PTRACE
2411 changes in process.c/util.c: we might see
2412 the child's initial trap before we see the
2413 parent return from the clone syscall.
2414 Leave the child suspended until the parent
2415 returns from its system call. Only then
2416 will we have the association of parent and
2417 child so that we know how to do clearbpt
2418 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002419 tcp = alloctcb(pid);
Denys Vlasenko833fb132011-08-17 11:30:56 +02002420 tcp->flags |= TCB_ATTACHED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002421 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002422 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002423 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002424 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002425 else
2426 /* This can happen if a clone call used
2427 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002428#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002429 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002430 if (WIFSTOPPED(status))
2431 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002432 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002433 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002435 /* set current output file */
2436 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002437 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002438#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002439 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002440 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2441 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002443#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002444
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002446 if (pid == strace_child)
2447 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002448 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2450 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002451#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002452 tprintf("+++ killed by %s %s+++",
2453 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002454 WCOREDUMP(status) ? "(core dumped) " : "");
2455#else
2456 tprintf("+++ killed by %s +++",
2457 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002458#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002459 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002460 }
2461 droptcb(tcp);
2462 continue;
2463 }
2464 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002465 if (pid == strace_child)
2466 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002467 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002468 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002469 tprintf(" <unfinished ... exit status %d>\n",
2470 WEXITSTATUS(status));
2471 tcp_last = NULL;
2472 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002473 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2474 printleader(tcp);
2475 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2476 printtrailer();
2477 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478 droptcb(tcp);
2479 continue;
2480 }
2481 if (!WIFSTOPPED(status)) {
2482 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2483 droptcb(tcp);
2484 continue;
2485 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002486
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002487 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002488 /* Ptrace event (we ignore all of them for now) */
2489 goto tracing;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002490 }
2491
Roland McGrath02203312007-06-11 22:06:31 +00002492 /*
2493 * Interestingly, the process may stop
2494 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002495 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002496 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002497 * A no-MMU vforked child won't send up a signal,
2498 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002499 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002500 if ((tcp->flags & TCB_STARTUP) &&
2501 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002502 /*
2503 * This flag is there to keep us in sync.
2504 * Next time this process stops it should
2505 * really be entering a system call.
2506 */
2507 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002508 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002509 /*
2510 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002511 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002512 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2514 droptcb(tcp);
2515 cleanup();
2516 return -1;
2517 }
2518 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002519#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002520 if (ptrace_setoptions) {
2521 if (debug)
2522 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2523 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2524 if (errno != ESRCH) {
2525 /* Should never happen, really */
2526 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002527 }
2528 }
2529 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002530#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002531 goto tracing;
2532 }
2533
Denys Vlasenko75422762011-05-27 14:36:01 +02002534 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002535 if (WSTOPSIG(status) == SIGSTOP &&
2536 (tcp->flags & TCB_SIGTRAPPED)) {
2537 /*
2538 * Trapped attempt to block SIGTRAP
2539 * Hope we are back in control now.
2540 */
2541 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002542 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 cleanup();
2544 return -1;
2545 }
2546 continue;
2547 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002548 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002549 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002550 siginfo_t si;
2551#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002552 long pc = 0;
2553 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002554
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002555 upeek(tcp, PT_CR_IPSR, &psr);
2556 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002557
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002558# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002559 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002560# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002561# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002562#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002563# define PC_FORMAT_STR ""
2564# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002565#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002566 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002567 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2568 tprintf("--- ");
2569 printsiginfo(&si, verbose(tcp));
2570 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002571 strsignal(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002572 PC_FORMAT_ARG);
2573 } else
2574 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2575 strsignal(WSTOPSIG(status)),
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002576 signame(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002577 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002578 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002579 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002580 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002581 cleanup();
2582 return -1;
2583 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 continue;
2585 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002586
2587 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002588 if (interrupted)
2589 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002590
2591 /* This should be syscall entry or exit.
2592 * (Or it still can be that pesky post-execve SIGTRAP!)
2593 * Handle it.
2594 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002595 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2596 /* ptrace() failed in trace_syscall() with ESRCH.
2597 * Likely a result of process disappearing mid-flight.
2598 * Observed case: exit_group() terminating
2599 * all processes in thread group. In this case, threads
2600 * "disappear" in an unpredictable moment without any
2601 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002602 */
2603 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002604 if (tcp_last) {
2605 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002606 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002607 */
2608 tcp_last->flags |= TCB_REPRINT;
2609 tprintf(" <unfinished ...>");
2610 printtrailer();
2611 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002612 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002613 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002614 ptrace(PTRACE_KILL,
2615 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002616 droptcb(tcp);
2617 }
2618 continue;
2619 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002620 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002621 /* Remember current print column before continuing. */
2622 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002623 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002624 cleanup();
2625 return -1;
2626 }
2627 }
2628 return 0;
2629}
2630
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002631#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002632
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002633void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002634tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002635{
2636 va_list args;
2637
Andreas Schwabe5355de2009-10-27 16:56:43 +01002638 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002639 if (outf) {
2640 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002641 if (n < 0) {
2642 if (outf != stderr)
2643 perror(outfname == NULL
2644 ? "<writing to pipe>" : outfname);
2645 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002646 curcol += n;
2647 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002648 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002649}
2650
2651void
2652tprints(const char *str)
2653{
2654 if (outf) {
2655 int n = fputs(str, outf);
2656 if (n >= 0) {
2657 curcol += strlen(str);
2658 return;
2659 }
2660 if (outf != stderr)
2661 perror(outfname == NULL
2662 ? "<writing to pipe>" : outfname);
2663 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002664}
2665
2666void
Denys Vlasenko12014262011-05-30 14:00:14 +02002667printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002668{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002669 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002670 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002671 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002672 tprintf(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002673 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002674 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002675 tprintf("= ? <unavailable>\n");
2676 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002677 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002678 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002679 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002680 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002681 }
2682 curcol = 0;
2683 if ((followfork == 1 || pflag_seen > 1) && outfname)
2684 tprintf("%-5d ", tcp->pid);
2685 else if (nprocs > 1 && !outfname)
2686 tprintf("[pid %5u] ", tcp->pid);
2687 if (tflag) {
2688 char str[sizeof("HH:MM:SS")];
2689 struct timeval tv, dtv;
2690 static struct timeval otv;
2691
2692 gettimeofday(&tv, NULL);
2693 if (rflag) {
2694 if (otv.tv_sec == 0)
2695 otv = tv;
2696 tv_sub(&dtv, &tv, &otv);
2697 tprintf("%6ld.%06ld ",
2698 (long) dtv.tv_sec, (long) dtv.tv_usec);
2699 otv = tv;
2700 }
2701 else if (tflag > 2) {
2702 tprintf("%ld.%06ld ",
2703 (long) tv.tv_sec, (long) tv.tv_usec);
2704 }
2705 else {
2706 time_t local = tv.tv_sec;
2707 strftime(str, sizeof(str), "%T", localtime(&local));
2708 if (tflag > 1)
2709 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2710 else
2711 tprintf("%s ", str);
2712 }
2713 }
2714 if (iflag)
2715 printcall(tcp);
2716}
2717
2718void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002719tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002720{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002721 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002722 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002723}
2724
2725void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002726printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002727{
2728 tprintf("\n");
2729 tcp_last = NULL;
2730}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002731
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002732#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002733
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002734int
2735mp_ioctl(int fd, int cmd, void *arg, int size)
2736{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002737 struct iovec iov[2];
2738 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002739
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002740 iov[0].iov_base = &cmd;
2741 iov[0].iov_len = sizeof cmd;
2742 if (arg) {
2743 ++n;
2744 iov[1].iov_base = arg;
2745 iov[1].iov_len = size;
2746 }
Roland McGrath553a6092002-12-16 20:40:39 +00002747
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002748 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002749}
2750
2751#endif