blob: afb5d29e511281232601b661611c96e369271574 [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
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200418 * 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();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200631 if (outf != stderr)
632 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000633#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200634# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000635 /* Kludge for SGI, see proc_open for details. */
636 sa.sa_handler = foobar;
637 sa.sa_flags = 0;
638 sigemptyset(&sa.sa_mask);
639 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200640# endif
641# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000642 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200643# else
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000644 kill(pid, SIGSTOP); /* stop HERE */
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200645# endif
Roland McGrath02203312007-06-11 22:06:31 +0000646#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000647 if (!daemonized_tracer) {
648 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200649 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 }
651 if (debug)
652 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000653 }
Roland McGrath02203312007-06-11 22:06:31 +0000654
655 if (username != NULL || geteuid() == 0) {
656 uid_t run_euid = run_uid;
657 gid_t run_egid = run_gid;
658
659 if (statbuf.st_mode & S_ISUID)
660 run_euid = statbuf.st_uid;
661 if (statbuf.st_mode & S_ISGID)
662 run_egid = statbuf.st_gid;
663
664 /*
665 * It is important to set groups before we
666 * lose privileges on setuid.
667 */
668 if (username != NULL) {
669 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200670 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000671 }
672 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200673 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000674 }
675 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200676 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000677 }
678 }
679 }
680 else
681 setreuid(run_uid, run_uid);
682
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 if (!daemonized_tracer) {
684 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200685 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000686 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200687 * the immediately following execve syscall.
688 * Can't do this on NOMMU systems, we are after
689 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000690 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400691 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200692 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000693 } else {
694 struct sigaction sv_sigchld;
695 sigaction(SIGCHLD, NULL, &sv_sigchld);
696 /*
697 * Make sure it is not SIG_IGN, otherwise wait
698 * will not block.
699 */
700 signal(SIGCHLD, SIG_DFL);
701 /*
702 * Wait for grandchild to attach to us.
703 * It kills child after that, and wait() unblocks.
704 */
705 alarm(3);
706 wait(NULL);
707 alarm(0);
708 sigaction(SIGCHLD, &sv_sigchld, NULL);
709 }
Roland McGrath02203312007-06-11 22:06:31 +0000710#endif /* !USE_PROCFS */
711
712 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200713 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000714 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000715
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200716 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200717
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200718 if (!daemonized_tracer) {
719 tcp = alloctcb(pid);
720 }
721 else {
722 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
723 strace_tracer_pid = getpid();
724 /* The tracee is our parent: */
725 pid = getppid();
726 tcp = alloctcb(pid);
727 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000728 tcp->flags |= TCB_ATTACHED;
729 }
Roland McGrath02203312007-06-11 22:06:31 +0000730#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000731 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200732 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000733 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200734#endif
Roland McGrath02203312007-06-11 22:06:31 +0000735}
736
Wang Chaob13c0de2010-11-12 17:25:19 +0800737#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000738static void kill_save_errno(pid_t pid, int sig)
739{
740 int saved_errno = errno;
741
742 (void) kill(pid, sig);
743 errno = saved_errno;
744}
745
Wang Chaob13c0de2010-11-12 17:25:19 +0800746/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000747 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800748 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000749 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800750 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000751static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200752test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800753{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000754 int pid, expected_grandchild = 0, found_grandchild = 0;
755 const unsigned int test_options = PTRACE_O_TRACECLONE |
756 PTRACE_O_TRACEFORK |
757 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800758
Denys Vlasenko5d645812011-08-20 12:48:18 +0200759 pid = fork();
760 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000761 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200762 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000763 pid = getpid();
764 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
765 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
766 __func__);
767 kill(pid, SIGSTOP);
768 if (fork() < 0)
769 perror_msg_and_die("fork");
770 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800771 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000772
773 while (1) {
774 int status, tracee_pid;
775
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000776 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000777 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000778 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000779 if (errno == EINTR)
780 continue;
781 else if (errno == ECHILD)
782 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000783 kill_save_errno(pid, SIGKILL);
784 perror_msg_and_die("%s: unexpected wait result %d",
785 __func__, tracee_pid);
786 }
787 if (WIFEXITED(status)) {
788 if (WEXITSTATUS(status)) {
789 if (tracee_pid != pid)
790 kill_save_errno(pid, SIGKILL);
791 error_msg_and_die("%s: unexpected exit status %u",
792 __func__, WEXITSTATUS(status));
793 }
794 continue;
795 }
796 if (WIFSIGNALED(status)) {
797 if (tracee_pid != pid)
798 kill_save_errno(pid, SIGKILL);
799 error_msg_and_die("%s: unexpected signal %u",
800 __func__, WTERMSIG(status));
801 }
802 if (!WIFSTOPPED(status)) {
803 if (tracee_pid != pid)
804 kill_save_errno(tracee_pid, SIGKILL);
805 kill(pid, SIGKILL);
806 error_msg_and_die("%s: unexpected wait status %x",
807 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000808 }
809 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000810 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000811 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
812 kill_save_errno(tracee_pid, SIGKILL);
813 kill_save_errno(pid, SIGKILL);
814 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800815 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000816 continue;
817 }
818 switch (WSTOPSIG(status)) {
819 case SIGSTOP:
820 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
821 && errno != EINVAL && errno != EIO)
822 perror_msg("PTRACE_SETOPTIONS");
823 break;
824 case SIGTRAP:
825 if (status >> 16 == PTRACE_EVENT_FORK) {
826 long msg = 0;
827
828 if (ptrace(PTRACE_GETEVENTMSG, pid,
829 NULL, (long) &msg) == 0)
830 expected_grandchild = msg;
831 }
832 break;
833 }
834 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
835 kill_save_errno(pid, SIGKILL);
836 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800837 }
838 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000839 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200840 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000841 if (debug)
842 fprintf(stderr, "ptrace_setoptions = %#x\n",
843 ptrace_setoptions);
844 return;
845 }
846 error_msg("Test for PTRACE_O_TRACECLONE failed, "
847 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800848}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200849
850/*
851 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
852 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
853 * and then see whether it will stop with (SIGTRAP | 0x80).
854 *
855 * Use of this option enables correct handling of user-generated SIGTRAPs,
856 * and SIGTRAPs generated by special instructions such as int3 on x86:
857 * _start: .globl _start
858 * int3
859 * movl $42, %ebx
860 * movl $1, %eax
861 * int $0x80
862 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
863 */
864static void
865test_ptrace_setoptions_for_all(void)
866{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000867 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
868 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200869 int pid;
870 int it_worked = 0;
871
872 pid = fork();
873 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200874 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200875
876 if (pid == 0) {
877 pid = getpid();
878 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200879 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000880 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
881 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200882 kill(pid, SIGSTOP);
883 _exit(0); /* parent should see entry into this syscall */
884 }
885
886 while (1) {
887 int status, tracee_pid;
888
889 errno = 0;
890 tracee_pid = wait(&status);
891 if (tracee_pid <= 0) {
892 if (errno == EINTR)
893 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000894 kill_save_errno(pid, SIGKILL);
895 perror_msg_and_die("%s: unexpected wait result %d",
896 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200897 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200898 if (WIFEXITED(status)) {
899 if (WEXITSTATUS(status) == 0)
900 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000901 error_msg_and_die("%s: unexpected exit status %u",
902 __func__, WEXITSTATUS(status));
903 }
904 if (WIFSIGNALED(status)) {
905 error_msg_and_die("%s: unexpected signal %u",
906 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200907 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200908 if (!WIFSTOPPED(status)) {
909 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000910 error_msg_and_die("%s: unexpected wait status %x",
911 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200912 }
913 if (WSTOPSIG(status) == SIGSTOP) {
914 /*
915 * We don't check "options aren't accepted" error.
916 * If it happens, we'll never get (SIGTRAP | 0x80),
917 * and thus will decide to not use the option.
918 * IOW: the outcome of the test will be correct.
919 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000920 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
921 && errno != EINVAL && errno != EIO)
922 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200923 }
924 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
925 it_worked = 1;
926 }
927 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000928 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200929 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200930 }
931 }
932
933 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200934 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200935 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200936 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200937 fprintf(stderr, "ptrace_setoptions = %#x\n",
938 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200939 return;
940 }
941
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000942 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
943 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200944}
Wang Chaob13c0de2010-11-12 17:25:19 +0800945#endif
946
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000947int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000948main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950 struct tcb *tcp;
951 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000952 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 struct sigaction sa;
954
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000955 progname = argv[0] ? argv[0] : "strace";
956
Denys Vlasenko75422762011-05-27 14:36:01 +0200957 strace_tracer_pid = getpid();
958
Roland McGrathee9d4352002-12-18 04:16:10 +0000959 /* Allocate the initial tcbtab. */
960 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200961 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200962 if (!tcbtab)
963 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200964 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200965 if (!tcp)
966 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200967 for (c = 0; c < tcbtabsize; c++)
968 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000969
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970 outf = stderr;
971 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000972 set_sortby(DEFAULT_SORTBY);
973 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 qualify("trace=all");
975 qualify("abbrev=all");
976 qualify("verbose=all");
977 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000979 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000980#ifndef USE_PROCFS
981 "D"
982#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000983 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 switch (c) {
985 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000986 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200987 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000988 }
989 cflag = CFLAG_ONLY_STATS;
990 break;
991 case 'C':
992 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200993 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000994 }
995 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 break;
997 case 'd':
998 debug++;
999 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001000#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001001 case 'D':
1002 daemonized_tracer = 1;
1003 break;
1004#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001005 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001006 optF = 1;
1007 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 case 'f':
1009 followfork++;
1010 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011 case 'h':
1012 usage(stdout, 0);
1013 break;
1014 case 'i':
1015 iflag++;
1016 break;
1017 case 'q':
1018 qflag++;
1019 break;
1020 case 'r':
1021 rflag++;
1022 tflag++;
1023 break;
1024 case 't':
1025 tflag++;
1026 break;
1027 case 'T':
1028 dtime++;
1029 break;
1030 case 'x':
1031 xflag++;
1032 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001033 case 'y':
1034 show_fd_path = 1;
1035 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 case 'v':
1037 qualify("abbrev=none");
1038 break;
1039 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001040 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 exit(0);
1042 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001043 case 'z':
1044 not_failing_only = 1;
1045 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 case 'a':
1047 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001048 if (acolumn < 0)
1049 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 break;
1051 case 'e':
1052 qualify(optarg);
1053 break;
1054 case 'o':
1055 outfname = strdup(optarg);
1056 break;
1057 case 'O':
1058 set_overhead(atoi(optarg));
1059 break;
1060 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001061 pid = atoi(optarg);
1062 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001063 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 break;
1065 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001066 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001067 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 break;
1069 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001070 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 tcp->flags |= TCB_ATTACHED;
1072 pflag_seen++;
1073 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001074 case 'P':
1075 tracing_paths = 1;
1076 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001077 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001078 }
1079 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001080 case 's':
1081 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001082 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001083 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001084 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085 break;
1086 case 'S':
1087 set_sortby(optarg);
1088 break;
1089 case 'u':
1090 username = strdup(optarg);
1091 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001092 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001093 if (putenv(optarg) < 0)
1094 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001095 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096 default:
1097 usage(stderr, 1);
1098 break;
1099 }
1100 }
1101
Denys Vlasenko102ec492011-08-25 01:27:59 +02001102 acolumn_spaces = malloc(acolumn + 1);
1103 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001104 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001105 memset(acolumn_spaces, ' ', acolumn);
1106 acolumn_spaces[acolumn] = '\0';
1107
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001108 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001109 usage(stderr, 1);
1110
Wang Chaod322a4b2010-08-05 14:30:11 +08001111 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001112 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001113 }
1114
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001115 if (!followfork)
1116 followfork = optF;
1117
Roland McGrathcb9def62006-04-25 07:48:03 +00001118 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001119 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001120 }
1121
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 /* See if they want to run as another user. */
1123 if (username != NULL) {
1124 struct passwd *pent;
1125
1126 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001127 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001129 pent = getpwnam(username);
1130 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001131 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 }
1133 run_uid = pent->pw_uid;
1134 run_gid = pent->pw_gid;
1135 }
1136 else {
1137 run_uid = getuid();
1138 run_gid = getgid();
1139 }
1140
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001141#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001142 if (followfork)
1143 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001144 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001145#endif
1146
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 /* Check if they want to redirect the output. */
1148 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001149 /* See if they want to pipe the output. */
1150 if (outfname[0] == '|' || outfname[0] == '!') {
1151 /*
1152 * We can't do the <outfname>.PID funny business
1153 * when using popen, so prohibit it.
1154 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001155 if (followfork > 1)
1156 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1157 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001158 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001159 else if (followfork <= 1)
1160 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 }
1162
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001163 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1164 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001166 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001167 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001170 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001171
Roland McGrath54cc1c82007-11-03 23:34:11 +00001172 /* Valid states here:
1173 optind < argc pflag_seen outfname interactive
1174 1 0 0 1
1175 0 1 0 1
1176 1 0 1 0
1177 0 1 1 1
1178 */
1179
1180 /* STARTUP_CHILD must be called before the signal handlers get
1181 installed below as they are inherited into the spawned process.
1182 Also we do not need to be protected by them as during interruption
1183 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1184 if (!pflag_seen)
1185 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 sigemptyset(&empty_set);
1188 sigemptyset(&blocked_set);
1189 sa.sa_handler = SIG_IGN;
1190 sigemptyset(&sa.sa_mask);
1191 sa.sa_flags = 0;
1192 sigaction(SIGTTOU, &sa, NULL);
1193 sigaction(SIGTTIN, &sa, NULL);
1194 if (interactive) {
1195 sigaddset(&blocked_set, SIGHUP);
1196 sigaddset(&blocked_set, SIGINT);
1197 sigaddset(&blocked_set, SIGQUIT);
1198 sigaddset(&blocked_set, SIGPIPE);
1199 sigaddset(&blocked_set, SIGTERM);
1200 sa.sa_handler = interrupt;
1201#ifdef SUNOS4
1202 /* POSIX signals on sunos4.1 are a little broken. */
1203 sa.sa_flags = SA_INTERRUPT;
1204#endif /* SUNOS4 */
1205 }
1206 sigaction(SIGHUP, &sa, NULL);
1207 sigaction(SIGINT, &sa, NULL);
1208 sigaction(SIGQUIT, &sa, NULL);
1209 sigaction(SIGPIPE, &sa, NULL);
1210 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001211#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 sa.sa_handler = reaper;
1213 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001214#else
1215 /* Make sure SIGCHLD has the default action so that waitpid
1216 definitely works without losing track of children. The user
1217 should not have given us a bogus state to inherit, but he might
1218 have. Arguably we should detect SIG_IGN here and pass it on
1219 to children, but probably noone really needs that. */
1220 sa.sa_handler = SIG_DFL;
1221 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001222#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001224 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001225 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001226
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227 if (trace() < 0)
1228 exit(1);
1229 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001230 fflush(NULL);
1231 if (exit_code > 0xff) {
1232 /* Child was killed by a signal, mimic that. */
1233 exit_code &= 0xff;
1234 signal(exit_code, SIG_DFL);
1235 raise(exit_code);
1236 /* Paranoia - what if this signal is not fatal?
1237 Exit with 128 + signo then. */
1238 exit_code += 128;
1239 }
1240 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241}
1242
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001243static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001244expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001245{
1246 /* Allocate some more TCBs and expand the table.
1247 We don't want to relocate the TCBs because our
1248 callers have pointers and it would be a pain.
1249 So tcbtab is a table of pointers. Since we never
1250 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001251 int i = tcbtabsize;
1252 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1253 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001254 if (!newtab || !newtcbs)
1255 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001256 tcbtabsize *= 2;
1257 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001258 while (i < tcbtabsize)
1259 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001260}
1261
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001263alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264{
1265 int i;
1266 struct tcb *tcp;
1267
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001268 if (nprocs == tcbtabsize)
1269 expand_tcbtab();
1270
Roland McGrathee9d4352002-12-18 04:16:10 +00001271 for (i = 0; i < tcbtabsize; i++) {
1272 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001273 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001274 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001275 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 tcp->flags = TCB_INUSE | TCB_STARTUP;
1277 tcp->outf = outf; /* Initialise to current out file */
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001278#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001280#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001282 if (debug)
1283 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001284 if (command_options_parsed)
1285 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286 return tcp;
1287 }
1288 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001289 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290}
1291
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001292#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001294proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295{
1296 char proc[32];
1297 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001298#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001299 int i;
1300 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001301 sigset_t signals;
1302 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001303#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304#ifndef HAVE_POLLABLE_PROCFS
1305 static int last_pfd;
1306#endif
1307
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001308#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001309 /* Open the process pseudo-files in /proc. */
1310 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001311 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1312 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 perror("strace: open(\"/proc/...\", ...)");
1314 return -1;
1315 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001316 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001317 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001318 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1319 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001320 perror("strace: open(\"/proc/...\", ...)");
1321 return -1;
1322 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001323 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001324 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001325 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1326 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001327 perror("strace: open(\"/proc/...\", ...)");
1328 return -1;
1329 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001330 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001331#else
1332 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001333# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001334 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001335 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001336# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001338 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001339# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001340 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001341 perror("strace: open(\"/proc/...\", ...)");
1342 return -1;
1343 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001344 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001345#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001346#ifdef FREEBSD
1347 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001348 tcp->pfd_reg = open(proc, O_RDONLY);
1349 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001350 perror("strace: open(\"/proc/.../regs\", ...)");
1351 return -1;
1352 }
1353 if (cflag) {
1354 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001355 tcp->pfd_status = open(proc, O_RDONLY);
1356 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001357 perror("strace: open(\"/proc/.../status\", ...)");
1358 return -1;
1359 }
1360 } else
1361 tcp->pfd_status = -1;
1362#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001363 rebuild_pollv();
1364 if (!attaching) {
1365 /*
1366 * Wait for the child to pause. Because of a race
1367 * condition we have to poll for the event.
1368 */
1369 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001370 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001371 perror("strace: PIOCSTATUS");
1372 return -1;
1373 }
1374 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001375 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001376 }
1377 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001378#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001379 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001380 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001381 perror("strace: PIOCSTOP");
1382 return -1;
1383 }
Roland McGrath553a6092002-12-16 20:40:39 +00001384#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385#ifdef PIOCSET
1386 /* Set Run-on-Last-Close. */
1387 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001388 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389 perror("PIOCSET PR_RLC");
1390 return -1;
1391 }
1392 /* Set or Reset Inherit-on-Fork. */
1393 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001394 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395 perror("PIOC{SET,RESET} PR_FORK");
1396 return -1;
1397 }
1398#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001399#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001400 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1401 perror("PIOCSRLC");
1402 return -1;
1403 }
1404 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1405 perror("PIOC{S,R}FORK");
1406 return -1;
1407 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001408#else /* FREEBSD */
1409 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1410 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1411 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001412 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001413 }
1414 arg &= ~PF_LINGER;
1415 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001416 perror("PIOCSFL");
1417 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001418 }
1419#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001420#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001421#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001422 /* Enable all syscall entries we care about. */
1423 premptyset(&syscalls);
1424 for (i = 1; i < MAX_QUALS; ++i) {
1425 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001426 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001427 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001428 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001429 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001430 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001431#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001432 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001433#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001434#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001435 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001436#endif
1437#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001438 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001439#endif
1440#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001441 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001442#endif
1443 }
1444 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 perror("PIOCSENTRY");
1446 return -1;
1447 }
John Hughes19e49982001-10-19 08:59:12 +00001448 /* Enable the syscall exits. */
1449 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 perror("PIOSEXIT");
1451 return -1;
1452 }
John Hughes19e49982001-10-19 08:59:12 +00001453 /* Enable signals we care about. */
1454 premptyset(&signals);
1455 for (i = 1; i < MAX_QUALS; ++i) {
1456 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001457 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001458 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001459 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 perror("PIOCSTRACE");
1461 return -1;
1462 }
John Hughes19e49982001-10-19 08:59:12 +00001463 /* Enable faults we care about */
1464 premptyset(&faults);
1465 for (i = 1; i < MAX_QUALS; ++i) {
1466 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001467 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001468 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001469 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470 perror("PIOCSFAULT");
1471 return -1;
1472 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001473#else /* FREEBSD */
1474 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001475 arg = S_SIG | S_SCE | S_SCX;
1476 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001477 perror("PIOCBIS");
1478 return -1;
1479 }
1480#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481 if (!attaching) {
1482#ifdef MIPS
1483 /*
1484 * The SGI PRSABORT doesn't work for pause() so
1485 * we send it a caught signal to wake it up.
1486 */
1487 kill(tcp->pid, SIGINT);
1488#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001489#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001491 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001492 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493 perror("PIOCRUN");
1494 return -1;
1495 }
Roland McGrath553a6092002-12-16 20:40:39 +00001496#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001497#endif /* !MIPS*/
1498#ifdef FREEBSD
1499 /* wake up the child if it received the SIGSTOP */
1500 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001501#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 for (;;) {
1503 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001504 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505 perror("PIOCWSTOP");
1506 return -1;
1507 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001508 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001509 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001510 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001511 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 break;
1513 }
1514 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001515#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001516 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001517 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1518#else
1519 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1520#endif
1521 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 perror("PIOCRUN");
1523 return -1;
1524 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001525#ifdef FREEBSD
1526 /* handle the case where we "opened" the child before
1527 it did the kill -STOP */
1528 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1529 tcp->status.PR_WHAT == SIGSTOP)
1530 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001531#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532 }
1533 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001534#ifdef FREEBSD
1535 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001536 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001537 /* We are attaching to an already running process.
1538 * Try to figure out the state of the process in syscalls,
1539 * to handle the first event well.
1540 * This is done by having a look at the "wchan" property of the
1541 * process, which tells where it is stopped (if it is). */
1542 FILE * status;
1543 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001544
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001545 sprintf(proc, "/proc/%d/status", tcp->pid);
1546 status = fopen(proc, "r");
1547 if (status &&
1548 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1549 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1550 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1551 strcmp(wchan, "stopevent")) {
1552 /* The process is asleep in the middle of a syscall.
1553 Fake the syscall entry event */
1554 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1555 tcp->status.PR_WHY = PR_SYSENTRY;
1556 trace_syscall(tcp);
1557 }
1558 if (status)
1559 fclose(status);
1560 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001561 }
1562#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563#ifndef HAVE_POLLABLE_PROCFS
1564 if (proc_poll_pipe[0] != -1)
1565 proc_poller(tcp->pfd);
1566 else if (nprocs > 1) {
1567 proc_poll_open();
1568 proc_poller(last_pfd);
1569 proc_poller(tcp->pfd);
1570 }
1571 last_pfd = tcp->pfd;
1572#endif /* !HAVE_POLLABLE_PROCFS */
1573 return 0;
1574}
1575
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001576#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001578struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001579pid2tcb(int pid)
1580{
1581 int i;
1582
1583 if (pid <= 0)
1584 return NULL;
1585
1586 for (i = 0; i < tcbtabsize; i++) {
1587 struct tcb *tcp = tcbtab[i];
1588 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1589 return tcp;
1590 }
1591
1592 return NULL;
1593}
1594
1595#ifdef USE_PROCFS
1596
1597static struct tcb *
1598first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599{
1600 int i;
1601 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001602 for (i = 0; i < tcbtabsize; i++) {
1603 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604 if (tcp->flags & TCB_INUSE)
1605 return tcp;
1606 }
1607 return NULL;
1608}
1609
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001611pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612{
1613 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614
Roland McGrathca16be82003-01-10 19:55:28 +00001615 for (i = 0; i < tcbtabsize; i++) {
1616 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617 if (tcp->pfd != pfd)
1618 continue;
1619 if (tcp->flags & TCB_INUSE)
1620 return tcp;
1621 }
1622 return NULL;
1623}
1624
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001625#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626
1627void
Denys Vlasenko12014262011-05-30 14:00:14 +02001628droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629{
1630 if (tcp->pid == 0)
1631 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001632
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001634 if (debug)
1635 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001636
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001637#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 if (tcp->pfd != -1) {
1639 close(tcp->pfd);
1640 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001641# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001642 if (tcp->pfd_reg != -1) {
1643 close(tcp->pfd_reg);
1644 tcp->pfd_reg = -1;
1645 }
1646 if (tcp->pfd_status != -1) {
1647 close(tcp->pfd_status);
1648 tcp->pfd_status = -1;
1649 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001650# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001651 tcp->flags = 0; /* rebuild_pollv needs it */
1652 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001654#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001655
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001656 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001658
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001659 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660}
1661
Roland McGrath0a463882007-07-05 18:43:16 +00001662/* detach traced process; continue with sig
1663 Never call DETACH twice on the same process as both unattached and
1664 attached-unstopped processes give the same ESRCH. For unattached process we
1665 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666
1667static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001668detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669{
1670 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001671#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001672 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001673#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674
1675 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001676 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
1678#ifdef LINUX
1679 /*
1680 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001681 * before detaching. Arghh. We go through hoops
1682 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001684#if defined(SPARC)
1685#undef PTRACE_DETACH
1686#define PTRACE_DETACH PTRACE_SUNDETACH
1687#endif
Roland McGrath02203312007-06-11 22:06:31 +00001688 /*
1689 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1690 * expected SIGSTOP. We must catch exactly one as otherwise the
1691 * detached process would be left stopped (process state T).
1692 */
1693 catch_sigstop = (tcp->flags & TCB_STARTUP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001694 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1695 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001697 }
1698 else if (errno != ESRCH) {
1699 /* Shouldn't happen. */
1700 perror("detach: ptrace(PTRACE_DETACH, ...)");
1701 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001702 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001703 if (errno != ESRCH)
1704 perror("detach: checking sanity");
1705 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001706 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001707 if (errno != ESRCH)
1708 perror("detach: stopping child");
1709 }
Roland McGrath02203312007-06-11 22:06:31 +00001710 else
1711 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001712 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001714#ifdef __WALL
1715 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1716 if (errno == ECHILD) /* Already gone. */
1717 break;
1718 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001719 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001720 break;
1721 }
1722#endif /* __WALL */
1723 /* No __WALL here. */
1724 if (waitpid(tcp->pid, &status, 0) < 0) {
1725 if (errno != ECHILD) {
1726 perror("detach: waiting");
1727 break;
1728 }
1729#ifdef __WCLONE
1730 /* If no processes, try clones. */
1731 if (wait4(tcp->pid, &status, __WCLONE,
1732 NULL) < 0) {
1733 if (errno != ECHILD)
1734 perror("detach: waiting");
1735 break;
1736 }
1737#endif /* __WCLONE */
1738 }
1739#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001740 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001741#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742 if (!WIFSTOPPED(status)) {
1743 /* Au revoir, mon ami. */
1744 break;
1745 }
1746 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001747 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748 break;
1749 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001750 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001751 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001752 : WSTOPSIG(status));
1753 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001756 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001757#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
1759#if defined(SUNOS4)
1760 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1761 if (sig && kill(tcp->pid, sig) < 0)
1762 perror("detach: kill");
1763 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001764 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765#endif /* SUNOS4 */
1766
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 if (!qflag)
1768 fprintf(stderr, "Process %u detached\n", tcp->pid);
1769
1770 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001771
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 return error;
1773}
1774
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001775#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001777static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778{
1779 int pid;
1780 int status;
1781
1782 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783 }
1784}
1785
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001786#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787
1788static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001789cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790{
1791 int i;
1792 struct tcb *tcp;
1793
Roland McGrathee9d4352002-12-18 04:16:10 +00001794 for (i = 0; i < tcbtabsize; i++) {
1795 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 if (!(tcp->flags & TCB_INUSE))
1797 continue;
1798 if (debug)
1799 fprintf(stderr,
1800 "cleanup: looking at pid %u\n", tcp->pid);
1801 if (tcp_last &&
1802 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001803 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001804 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 }
1806 if (tcp->flags & TCB_ATTACHED)
1807 detach(tcp, 0);
1808 else {
1809 kill(tcp->pid, SIGCONT);
1810 kill(tcp->pid, SIGTERM);
1811 }
1812 }
1813 if (cflag)
1814 call_summary(outf);
1815}
1816
1817static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001818interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819{
1820 interrupted = 1;
1821}
1822
1823#ifndef HAVE_STRERROR
1824
Roland McGrath6d2b3492002-12-30 00:51:30 +00001825#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826extern int sys_nerr;
1827extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001828#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829
1830const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001831strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832{
1833 static char buf[64];
1834
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001835 if (err_no < 1 || err_no >= sys_nerr) {
1836 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837 return buf;
1838 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001839 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001840}
1841
1842#endif /* HAVE_STERRROR */
1843
1844#ifndef HAVE_STRSIGNAL
1845
Roland McGrath8f474e02003-01-14 07:53:33 +00001846#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001847extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001849#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1850extern char *_sys_siglist[];
1851#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852
1853const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001854strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001855{
1856 static char buf[64];
1857
1858 if (sig < 1 || sig >= NSIG) {
1859 sprintf(buf, "Unknown signal %d", sig);
1860 return buf;
1861 }
1862#ifdef HAVE__SYS_SIGLIST
1863 return _sys_siglist[sig];
1864#else
1865 return sys_siglist[sig];
1866#endif
1867}
1868
1869#endif /* HAVE_STRSIGNAL */
1870
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001871#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872
1873static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001874rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875{
1876 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001878 free(pollv);
1879 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001880 if (!pollv)
1881 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001882
Roland McGrathca16be82003-01-10 19:55:28 +00001883 for (i = j = 0; i < tcbtabsize; i++) {
1884 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885 if (!(tcp->flags & TCB_INUSE))
1886 continue;
1887 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001888 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001889 j++;
1890 }
1891 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001892 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893 }
1894}
1895
1896#ifndef HAVE_POLLABLE_PROCFS
1897
1898static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001899proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001900{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901 int i;
1902
1903 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001904 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 }
1906 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001907 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001908 }
1909}
1910
1911static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001912proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913{
1914 int i;
1915 int n;
1916 struct proc_pollfd pollinfo;
1917
Denys Vlasenko5d645812011-08-20 12:48:18 +02001918 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1919 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001920 return n;
1921 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001922 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923 }
1924 for (i = 0; i < nprocs; i++) {
1925 if (pollv[i].fd == pollinfo.fd)
1926 pollv[i].revents = pollinfo.revents;
1927 else
1928 pollv[i].revents = 0;
1929 }
1930 poller_pid = pollinfo.pid;
1931 return 1;
1932}
1933
1934static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001935wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936{
1937}
1938
1939static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001940proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001941{
1942 struct proc_pollfd pollinfo;
1943 struct sigaction sa;
1944 sigset_t blocked_set, empty_set;
1945 int i;
1946 int n;
1947 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001948#ifdef FREEBSD
1949 struct procfs_status pfs;
1950#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001951
1952 switch (fork()) {
1953 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001954 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 case 0:
1956 break;
1957 default:
1958 return;
1959 }
1960
1961 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1962 sa.sa_flags = 0;
1963 sigemptyset(&sa.sa_mask);
1964 sigaction(SIGHUP, &sa, NULL);
1965 sigaction(SIGINT, &sa, NULL);
1966 sigaction(SIGQUIT, &sa, NULL);
1967 sigaction(SIGPIPE, &sa, NULL);
1968 sigaction(SIGTERM, &sa, NULL);
1969 sa.sa_handler = wakeup_handler;
1970 sigaction(SIGUSR1, &sa, NULL);
1971 sigemptyset(&blocked_set);
1972 sigaddset(&blocked_set, SIGUSR1);
1973 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1974 sigemptyset(&empty_set);
1975
1976 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001977 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001978 }
1979 n = rl.rlim_cur;
1980 for (i = 0; i < n; i++) {
1981 if (i != pfd && i != proc_poll_pipe[1])
1982 close(i);
1983 }
1984
1985 pollinfo.fd = pfd;
1986 pollinfo.pid = getpid();
1987 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001988#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001989 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1990#else
1991 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1992#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001993 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001994 switch (errno) {
1995 case EINTR:
1996 continue;
1997 case EBADF:
1998 pollinfo.revents = POLLERR;
1999 break;
2000 case ENOENT:
2001 pollinfo.revents = POLLHUP;
2002 break;
2003 default:
2004 perror("proc_poller: PIOCWSTOP");
2005 }
2006 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2007 _exit(0);
2008 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002009 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2011 sigsuspend(&empty_set);
2012 }
2013}
2014
2015#endif /* !HAVE_POLLABLE_PROCFS */
2016
2017static int
2018choose_pfd()
2019{
2020 int i, j;
2021 struct tcb *tcp;
2022
2023 static int last;
2024
2025 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002026 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002027 /*
2028 * The previous process is ready to run again. We'll
2029 * let it do so if it is currently in a syscall. This
2030 * heuristic improves the readability of the trace.
2031 */
2032 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002033 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 return pollv[last].fd;
2035 }
2036
2037 for (i = 0; i < nprocs; i++) {
2038 /* Let competing children run round robin. */
2039 j = (i + last + 1) % nprocs;
2040 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2041 tcp = pfd2tcb(pollv[j].fd);
2042 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002043 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044 }
2045 droptcb(tcp);
2046 return -1;
2047 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002048 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049 last = j;
2050 return pollv[j].fd;
2051 }
2052 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002053 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054}
2055
2056static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002057trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002059#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002060 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002061#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062 struct tcb *tcp;
2063 int pfd;
2064 int what;
2065 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002066 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067
2068 for (;;) {
2069 if (interactive)
2070 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2071
2072 if (nprocs == 0)
2073 break;
2074
2075 switch (nprocs) {
2076 case 1:
2077#ifndef HAVE_POLLABLE_PROCFS
2078 if (proc_poll_pipe[0] == -1) {
2079#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002080 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081 if (!tcp)
2082 continue;
2083 pfd = tcp->pfd;
2084 if (pfd == -1)
2085 continue;
2086 break;
2087#ifndef HAVE_POLLABLE_PROCFS
2088 }
2089 /* fall through ... */
2090#endif /* !HAVE_POLLABLE_PROCFS */
2091 default:
2092#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002093#ifdef POLL_HACK
2094 /* On some systems (e.g. UnixWare) we get too much ugly
2095 "unfinished..." stuff when multiple proceses are in
2096 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002097
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002098 if (in_syscall) {
2099 struct pollfd pv;
2100 tcp = in_syscall;
2101 in_syscall = NULL;
2102 pv.fd = tcp->pfd;
2103 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002104 what = poll(&pv, 1, 1);
2105 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002106 if (interrupted)
2107 return 0;
2108 continue;
2109 }
2110 else if (what == 1 && pv.revents & POLLWANT) {
2111 goto FOUND;
2112 }
2113 }
2114#endif
2115
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 if (poll(pollv, nprocs, INFTIM) < 0) {
2117 if (interrupted)
2118 return 0;
2119 continue;
2120 }
2121#else /* !HAVE_POLLABLE_PROCFS */
2122 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2123 if (interrupted)
2124 return 0;
2125 continue;
2126 }
2127#endif /* !HAVE_POLLABLE_PROCFS */
2128 pfd = choose_pfd();
2129 if (pfd == -1)
2130 continue;
2131 break;
2132 }
2133
2134 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002135 tcp = pfd2tcb(pfd);
2136 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002137 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 }
John Hughesb6643082002-05-23 11:02:22 +00002139#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002140 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002141#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 /* Get the status of the process. */
2143 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002144#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002145 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002146#else /* FREEBSD */
2147 /* Thanks to some scheduling mystery, the first poller
2148 sometimes waits for the already processed end of fork
2149 event. Doing a non blocking poll here solves the problem. */
2150 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002151 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002152 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002153 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002154#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002155 ioctl_errno = errno;
2156#ifndef HAVE_POLLABLE_PROCFS
2157 if (proc_poll_pipe[0] != -1) {
2158 if (ioctl_result < 0)
2159 kill(poller_pid, SIGKILL);
2160 else
2161 kill(poller_pid, SIGUSR1);
2162 }
2163#endif /* !HAVE_POLLABLE_PROCFS */
2164 }
2165 if (interrupted)
2166 return 0;
2167
2168 if (interactive)
2169 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2170
2171 if (ioctl_result < 0) {
2172 /* Find out what happened if it failed. */
2173 switch (ioctl_errno) {
2174 case EINTR:
2175 case EBADF:
2176 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002177#ifdef FREEBSD
2178 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002179#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002180 case ENOENT:
2181 droptcb(tcp);
2182 continue;
2183 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002184 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002185 }
2186 }
2187
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002188#ifdef FREEBSD
2189 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2190 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002191 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002192 continue;
2193 }
Roland McGrath553a6092002-12-16 20:40:39 +00002194#endif
2195
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 /* clear the just started flag */
2197 tcp->flags &= ~TCB_STARTUP;
2198
2199 /* set current output file */
2200 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002201 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002202
2203 if (cflag) {
2204 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002205#ifdef FREEBSD
2206 char buf[1024];
2207 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208
Denys Vlasenko5d645812011-08-20 12:48:18 +02002209 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2210 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002211 buf[len] = '\0';
2212 sscanf(buf,
2213 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2214 &stime.tv_sec, &stime.tv_usec);
2215 } else
2216 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002217#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2219 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002220#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2222 tcp->stime = stime;
2223 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002224 what = tcp->status.PR_WHAT;
2225 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002226#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002228 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2229 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002230 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002231 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002232 }
2233 }
2234 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002235#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002237#ifdef POLL_HACK
2238 in_syscall = tcp;
2239#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002240 case PR_SYSEXIT:
2241 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002242 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002243 }
2244 break;
2245 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002246 if (cflag != CFLAG_ONLY_STATS
2247 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248 printleader(tcp);
2249 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002250 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002251 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002252#ifdef PR_INFO
2253 if (tcp->status.PR_INFO.si_signo == what) {
2254 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002255 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002256 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002257 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002258 }
2259#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002260 }
2261 break;
2262 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002263 if (cflag != CFLAGS_ONLY_STATS
2264 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 printleader(tcp);
2266 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002267 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002268 }
2269 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002270#ifdef FREEBSD
2271 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002272 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002273#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002275 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002276 break;
2277 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002278 /* Remember current print column before continuing. */
2279 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002280 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002281#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002282 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002283#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002284 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002285#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002286 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002287 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288 }
2289 }
2290 return 0;
2291}
2292
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002293#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294
Roland McGratheb9e2e82009-06-02 16:49:22 -07002295static int
2296trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002297{
2298 int pid;
2299 int wait_errno;
2300 int status;
2301 struct tcb *tcp;
2302#ifdef LINUX
2303 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002304 struct rusage *rup = cflag ? &ru : NULL;
2305# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002306 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002307# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308#endif /* LINUX */
2309
Roland McGratheb9e2e82009-06-02 16:49:22 -07002310 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002311 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002312 return 0;
2313 if (interactive)
2314 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002315#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002316# ifdef __WALL
2317 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002318 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002319 /* this kernel does not support __WALL */
2320 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002321 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002322 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002323 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002324 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002325 pid = wait4(-1, &status, __WCLONE, rup);
2326 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002327 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002328 }
2329 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002330# else
2331 pid = wait4(-1, &status, 0, rup);
2332# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333#endif /* LINUX */
2334#ifdef SUNOS4
2335 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002336#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002338 if (interactive)
2339 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002341 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002342 switch (wait_errno) {
2343 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002344 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002345 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002346 /*
2347 * We would like to verify this case
2348 * but sometimes a race in Solbourne's
2349 * version of SunOS sometimes reports
2350 * ECHILD before sending us SIGCHILD.
2351 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002352 return 0;
2353 default:
2354 errno = wait_errno;
2355 perror("strace: wait");
2356 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002357 }
2358 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002359 if (pid == popen_pid) {
2360 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002361 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002362 continue;
2363 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002364 if (debug) {
2365 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2366#ifdef LINUX
2367 unsigned ev = (unsigned)status >> 16;
2368 if (ev) {
2369 static const char *const event_names[] = {
2370 [PTRACE_EVENT_CLONE] = "CLONE",
2371 [PTRACE_EVENT_FORK] = "FORK",
2372 [PTRACE_EVENT_VFORK] = "VFORK",
2373 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2374 [PTRACE_EVENT_EXEC] = "EXEC",
2375 [PTRACE_EVENT_EXIT] = "EXIT",
2376 };
2377 const char *e;
2378 if (ev < ARRAY_SIZE(event_names))
2379 e = event_names[ev];
2380 else {
2381 sprintf(buf, "?? (%u)", ev);
2382 e = buf;
2383 }
2384 fprintf(stderr, " PTRACE_EVENT_%s", e);
2385 }
2386#endif
2387 strcpy(buf, "???");
2388 if (WIFSIGNALED(status))
2389#ifdef WCOREDUMP
2390 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2391 WCOREDUMP(status) ? "core," : "",
2392 signame(WTERMSIG(status)));
2393#else
2394 sprintf(buf, "WIFSIGNALED,sig=%s",
2395 signame(WTERMSIG(status)));
2396#endif
2397 if (WIFEXITED(status))
2398 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2399 if (WIFSTOPPED(status))
2400 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002401#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002402 if (WIFCONTINUED(status))
2403 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002404#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002405 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2406 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002407
2408 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002409 tcp = pid2tcb(pid);
2410 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002411#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002412 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002413 /* This is needed to go with the CLONE_PTRACE
2414 changes in process.c/util.c: we might see
2415 the child's initial trap before we see the
2416 parent return from the clone syscall.
2417 Leave the child suspended until the parent
2418 returns from its system call. Only then
2419 will we have the association of parent and
2420 child so that we know how to do clearbpt
2421 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002422 tcp = alloctcb(pid);
Denys Vlasenko833fb132011-08-17 11:30:56 +02002423 tcp->flags |= TCB_ATTACHED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002424 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002425 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002426 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002427 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002428 else
2429 /* This can happen if a clone call used
2430 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002431#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002432 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002433 if (WIFSTOPPED(status))
2434 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002435 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002436 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002437 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002438 /* set current output file */
2439 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002440 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002441#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002442 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2444 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002446#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002447
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002448 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002449 if (pid == strace_child)
2450 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002451 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002452 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2453 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002454#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002455 tprintf("+++ killed by %s %s+++",
2456 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002457 WCOREDUMP(status) ? "(core dumped) " : "");
2458#else
2459 tprintf("+++ killed by %s +++",
2460 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002461#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002462 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002463 }
2464 droptcb(tcp);
2465 continue;
2466 }
2467 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002468 if (pid == strace_child)
2469 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002470 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002471 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002472 tprintf(" <unfinished ... exit status %d>\n",
2473 WEXITSTATUS(status));
2474 tcp_last = NULL;
2475 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002476 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2477 printleader(tcp);
2478 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2479 printtrailer();
2480 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002481 droptcb(tcp);
2482 continue;
2483 }
2484 if (!WIFSTOPPED(status)) {
2485 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2486 droptcb(tcp);
2487 continue;
2488 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002489
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002490 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002491 /* Ptrace event (we ignore all of them for now) */
2492 goto tracing;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002493 }
2494
Roland McGrath02203312007-06-11 22:06:31 +00002495 /*
2496 * Interestingly, the process may stop
2497 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002498 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002499 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002500 * A no-MMU vforked child won't send up a signal,
2501 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002502 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002503 if ((tcp->flags & TCB_STARTUP) &&
2504 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002505 /*
2506 * This flag is there to keep us in sync.
2507 * Next time this process stops it should
2508 * really be entering a system call.
2509 */
2510 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002511 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002512 /*
2513 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002514 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002515 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002516 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2517 droptcb(tcp);
2518 cleanup();
2519 return -1;
2520 }
2521 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002522#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002523 if (ptrace_setoptions) {
2524 if (debug)
2525 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2526 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2527 if (errno != ESRCH) {
2528 /* Should never happen, really */
2529 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002530 }
2531 }
2532 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002533#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 goto tracing;
2535 }
2536
Denys Vlasenko75422762011-05-27 14:36:01 +02002537 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002538 if (WSTOPSIG(status) == SIGSTOP &&
2539 (tcp->flags & TCB_SIGTRAPPED)) {
2540 /*
2541 * Trapped attempt to block SIGTRAP
2542 * Hope we are back in control now.
2543 */
2544 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002545 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 cleanup();
2547 return -1;
2548 }
2549 continue;
2550 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002551 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002552 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002553 siginfo_t si;
2554#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002555 long pc = 0;
2556 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002557
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002558 upeek(tcp, PT_CR_IPSR, &psr);
2559 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002560
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002561# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002562 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002563# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002564# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002565#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002566# define PC_FORMAT_STR ""
2567# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002568#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002569 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002570 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002571 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002572 printsiginfo(&si, verbose(tcp));
2573 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002574 strsignal(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002575 PC_FORMAT_ARG);
2576 } else
2577 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2578 strsignal(WSTOPSIG(status)),
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002579 signame(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002580 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002581 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002582 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002583 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 cleanup();
2585 return -1;
2586 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002587 continue;
2588 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002589
2590 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002591 if (interrupted)
2592 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002593
2594 /* This should be syscall entry or exit.
2595 * (Or it still can be that pesky post-execve SIGTRAP!)
2596 * Handle it.
2597 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002598 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2599 /* ptrace() failed in trace_syscall() with ESRCH.
2600 * Likely a result of process disappearing mid-flight.
2601 * Observed case: exit_group() terminating
2602 * all processes in thread group. In this case, threads
2603 * "disappear" in an unpredictable moment without any
2604 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002605 */
2606 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002607 if (tcp_last) {
2608 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002609 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002610 */
2611 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002612 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002613 printtrailer();
2614 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002616 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002617 ptrace(PTRACE_KILL,
2618 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619 droptcb(tcp);
2620 }
2621 continue;
2622 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002623 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002624 /* Remember current print column before continuing. */
2625 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002626 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627 cleanup();
2628 return -1;
2629 }
2630 }
2631 return 0;
2632}
2633
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002634#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002635
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002638{
2639 va_list args;
2640
Andreas Schwabe5355de2009-10-27 16:56:43 +01002641 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002642 if (outf) {
2643 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002644 if (n < 0) {
2645 if (outf != stderr)
2646 perror(outfname == NULL
2647 ? "<writing to pipe>" : outfname);
2648 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002649 curcol += n;
2650 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002651 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002652}
2653
2654void
2655tprints(const char *str)
2656{
2657 if (outf) {
2658 int n = fputs(str, outf);
2659 if (n >= 0) {
2660 curcol += strlen(str);
2661 return;
2662 }
2663 if (outf != stderr)
2664 perror(outfname == NULL
2665 ? "<writing to pipe>" : outfname);
2666 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002667}
2668
2669void
Denys Vlasenko12014262011-05-30 14:00:14 +02002670printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002671{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002672 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002673 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002674 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002675 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002676 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002677 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002678 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002679 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002680 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002681 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002682 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002683 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002684 }
2685 curcol = 0;
2686 if ((followfork == 1 || pflag_seen > 1) && outfname)
2687 tprintf("%-5d ", tcp->pid);
2688 else if (nprocs > 1 && !outfname)
2689 tprintf("[pid %5u] ", tcp->pid);
2690 if (tflag) {
2691 char str[sizeof("HH:MM:SS")];
2692 struct timeval tv, dtv;
2693 static struct timeval otv;
2694
2695 gettimeofday(&tv, NULL);
2696 if (rflag) {
2697 if (otv.tv_sec == 0)
2698 otv = tv;
2699 tv_sub(&dtv, &tv, &otv);
2700 tprintf("%6ld.%06ld ",
2701 (long) dtv.tv_sec, (long) dtv.tv_usec);
2702 otv = tv;
2703 }
2704 else if (tflag > 2) {
2705 tprintf("%ld.%06ld ",
2706 (long) tv.tv_sec, (long) tv.tv_usec);
2707 }
2708 else {
2709 time_t local = tv.tv_sec;
2710 strftime(str, sizeof(str), "%T", localtime(&local));
2711 if (tflag > 1)
2712 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2713 else
2714 tprintf("%s ", str);
2715 }
2716 }
2717 if (iflag)
2718 printcall(tcp);
2719}
2720
2721void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002722tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002723{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002724 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002725 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002726}
2727
2728void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002729printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002730{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002731 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002732 tcp_last = NULL;
2733}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002734
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002735#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002736
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002737int
2738mp_ioctl(int fd, int cmd, void *arg, int size)
2739{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002740 struct iovec iov[2];
2741 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002742
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002743 iov[0].iov_base = &cmd;
2744 iov[0].iov_len = sizeof cmd;
2745 if (arg) {
2746 ++n;
2747 iov[1].iov_base = arg;
2748 iov[1].iov_len = size;
2749 }
Roland McGrath553a6092002-12-16 20:40:39 +00002750
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002751 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002752}
2753
2754#endif