blob: c911ae412ed97ff5593a07e08f33233dc0282791 [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) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200427 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000428 }
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
Denys Vlasenkod116a732011-09-05 14:01:33 +0200447 /* Is this a process we should attach to, but not yet attached? */
448 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
449 continue; /* no */
450
451 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000452 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200453 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000454
455#ifdef USE_PROCFS
456 if (proc_open(tcp, 1) < 0) {
457 fprintf(stderr, "trouble opening proc file\n");
458 droptcb(tcp);
459 continue;
460 }
461#else /* !USE_PROCFS */
462# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000463 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000464 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000465 DIR *dir;
466
467 sprintf(procdir, "/proc/%d/task", tcp->pid);
468 dir = opendir(procdir);
469 if (dir != NULL) {
470 unsigned int ntid = 0, nerr = 0;
471 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200472
Roland McGrath02203312007-06-11 22:06:31 +0000473 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200474 struct tcb *cur_tcp;
475 int tid;
476
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000477 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000478 continue;
479 tid = atoi(de->d_name);
480 if (tid <= 0)
481 continue;
482 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200483 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000484 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200485 if (debug)
486 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200487 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200488 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200489 if (debug)
490 fprintf(stderr, "attach to pid %d succeeded\n", tid);
491 cur_tcp = tcp;
492 if (tid != tcp->pid)
493 cur_tcp = alloctcb(tid);
Denys Vlasenkod116a732011-09-05 14:01:33 +0200494 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP;
Roland McGrath02203312007-06-11 22:06:31 +0000495 }
496 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200497 if (interactive) {
498 sigprocmask(SIG_SETMASK, &empty_set, NULL);
499 if (interrupted)
500 goto ret;
501 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
502 }
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 Vlasenko381dbc22011-09-05 13:59:39 +0200524 tcp->flags |= TCB_STARTUP;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200525 if (debug)
526 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000527
528 if (daemonized_tracer) {
529 /*
530 * It is our grandparent we trace, not a -p PID.
531 * Don't want to just detach on exit, so...
532 */
533 tcp->flags &= ~TCB_ATTACHED;
534 /*
535 * Make parent go away.
536 * Also makes grandparent's wait() unblock.
537 */
538 kill(getppid(), SIGKILL);
539 }
540
Roland McGrath02203312007-06-11 22:06:31 +0000541#endif /* !USE_PROCFS */
542 if (!qflag)
543 fprintf(stderr,
544 "Process %u attached - interrupt to quit\n",
545 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200546 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000547
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200548 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000549 if (interactive)
550 sigprocmask(SIG_SETMASK, &empty_set, NULL);
551}
552
553static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200554startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000555{
556 struct stat statbuf;
557 const char *filename;
558 char pathname[MAXPATHLEN];
559 int pid = 0;
560 struct tcb *tcp;
561
562 filename = argv[0];
563 if (strchr(filename, '/')) {
564 if (strlen(filename) > sizeof pathname - 1) {
565 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200566 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000567 }
568 strcpy(pathname, filename);
569 }
570#ifdef USE_DEBUGGING_EXEC
571 /*
572 * Debuggers customarily check the current directory
573 * first regardless of the path but doing that gives
574 * security geeks a panic attack.
575 */
576 else if (stat(filename, &statbuf) == 0)
577 strcpy(pathname, filename);
578#endif /* USE_DEBUGGING_EXEC */
579 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000580 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000581 int m, n, len;
582
583 for (path = getenv("PATH"); path && *path; path += m) {
584 if (strchr(path, ':')) {
585 n = strchr(path, ':') - path;
586 m = n + 1;
587 }
588 else
589 m = n = strlen(path);
590 if (n == 0) {
591 if (!getcwd(pathname, MAXPATHLEN))
592 continue;
593 len = strlen(pathname);
594 }
595 else if (n > sizeof pathname - 1)
596 continue;
597 else {
598 strncpy(pathname, path, n);
599 len = n;
600 }
601 if (len && pathname[len - 1] != '/')
602 pathname[len++] = '/';
603 strcpy(pathname + len, filename);
604 if (stat(pathname, &statbuf) == 0 &&
605 /* Accept only regular files
606 with some execute bits set.
607 XXX not perfect, might still fail */
608 S_ISREG(statbuf.st_mode) &&
609 (statbuf.st_mode & 0111))
610 break;
611 }
612 }
613 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200614 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000615 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000616 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000617 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200618 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000619 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200620 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
621 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000622 ) {
623 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200624 if (outf != stderr)
625 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000626#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200627# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000628 /* Kludge for SGI, see proc_open for details. */
629 sa.sa_handler = foobar;
630 sa.sa_flags = 0;
631 sigemptyset(&sa.sa_mask);
632 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200633# endif
634# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000635 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200636# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200637 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200638# endif
Roland McGrath02203312007-06-11 22:06:31 +0000639#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000640 if (!daemonized_tracer) {
641 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200642 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000643 }
644 if (debug)
645 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000646 }
Roland McGrath02203312007-06-11 22:06:31 +0000647
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200648 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000649 uid_t run_euid = run_uid;
650 gid_t run_egid = run_gid;
651
652 if (statbuf.st_mode & S_ISUID)
653 run_euid = statbuf.st_uid;
654 if (statbuf.st_mode & S_ISGID)
655 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000656 /*
657 * It is important to set groups before we
658 * lose privileges on setuid.
659 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200660 if (initgroups(username, run_gid) < 0) {
661 perror_msg_and_die("initgroups");
662 }
663 if (setregid(run_gid, run_egid) < 0) {
664 perror_msg_and_die("setregid");
665 }
666 if (setreuid(run_uid, run_euid) < 0) {
667 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000668 }
669 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200670 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000671 setreuid(run_uid, run_uid);
672
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673 if (!daemonized_tracer) {
674 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200675 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200677 * the immediately following execve syscall.
678 * Can't do this on NOMMU systems, we are after
679 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000680 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400681 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200682 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 } else {
684 struct sigaction sv_sigchld;
685 sigaction(SIGCHLD, NULL, &sv_sigchld);
686 /*
687 * Make sure it is not SIG_IGN, otherwise wait
688 * will not block.
689 */
690 signal(SIGCHLD, SIG_DFL);
691 /*
692 * Wait for grandchild to attach to us.
693 * It kills child after that, and wait() unblocks.
694 */
695 alarm(3);
696 wait(NULL);
697 alarm(0);
698 sigaction(SIGCHLD, &sv_sigchld, NULL);
699 }
Roland McGrath02203312007-06-11 22:06:31 +0000700#endif /* !USE_PROCFS */
701
702 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200703 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000704 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000705
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200706 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200707
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200708 if (!daemonized_tracer) {
709 tcp = alloctcb(pid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200710 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200711 }
712 else {
713 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
714 strace_tracer_pid = getpid();
715 /* The tracee is our parent: */
716 pid = getppid();
717 tcp = alloctcb(pid);
718 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 tcp->flags |= TCB_ATTACHED;
720 }
Roland McGrath02203312007-06-11 22:06:31 +0000721#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200723 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000724 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200725#endif
Roland McGrath02203312007-06-11 22:06:31 +0000726}
727
Wang Chaob13c0de2010-11-12 17:25:19 +0800728#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000729static void kill_save_errno(pid_t pid, int sig)
730{
731 int saved_errno = errno;
732
733 (void) kill(pid, sig);
734 errno = saved_errno;
735}
736
Wang Chaob13c0de2010-11-12 17:25:19 +0800737/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000738 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800739 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000740 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800741 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000742static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200743test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800744{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000745 int pid, expected_grandchild = 0, found_grandchild = 0;
746 const unsigned int test_options = PTRACE_O_TRACECLONE |
747 PTRACE_O_TRACEFORK |
748 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800749
Denys Vlasenko5d645812011-08-20 12:48:18 +0200750 pid = fork();
751 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000752 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200753 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000754 pid = getpid();
755 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
756 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
757 __func__);
758 kill(pid, SIGSTOP);
759 if (fork() < 0)
760 perror_msg_and_die("fork");
761 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800762 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000763
764 while (1) {
765 int status, tracee_pid;
766
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000767 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000768 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000769 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000770 if (errno == EINTR)
771 continue;
772 else if (errno == ECHILD)
773 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000774 kill_save_errno(pid, SIGKILL);
775 perror_msg_and_die("%s: unexpected wait result %d",
776 __func__, tracee_pid);
777 }
778 if (WIFEXITED(status)) {
779 if (WEXITSTATUS(status)) {
780 if (tracee_pid != pid)
781 kill_save_errno(pid, SIGKILL);
782 error_msg_and_die("%s: unexpected exit status %u",
783 __func__, WEXITSTATUS(status));
784 }
785 continue;
786 }
787 if (WIFSIGNALED(status)) {
788 if (tracee_pid != pid)
789 kill_save_errno(pid, SIGKILL);
790 error_msg_and_die("%s: unexpected signal %u",
791 __func__, WTERMSIG(status));
792 }
793 if (!WIFSTOPPED(status)) {
794 if (tracee_pid != pid)
795 kill_save_errno(tracee_pid, SIGKILL);
796 kill(pid, SIGKILL);
797 error_msg_and_die("%s: unexpected wait status %x",
798 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000799 }
800 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000801 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000802 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
803 kill_save_errno(tracee_pid, SIGKILL);
804 kill_save_errno(pid, SIGKILL);
805 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800806 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000807 continue;
808 }
809 switch (WSTOPSIG(status)) {
810 case SIGSTOP:
811 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
812 && errno != EINVAL && errno != EIO)
813 perror_msg("PTRACE_SETOPTIONS");
814 break;
815 case SIGTRAP:
816 if (status >> 16 == PTRACE_EVENT_FORK) {
817 long msg = 0;
818
819 if (ptrace(PTRACE_GETEVENTMSG, pid,
820 NULL, (long) &msg) == 0)
821 expected_grandchild = msg;
822 }
823 break;
824 }
825 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
826 kill_save_errno(pid, SIGKILL);
827 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800828 }
829 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000830 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200831 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000832 if (debug)
833 fprintf(stderr, "ptrace_setoptions = %#x\n",
834 ptrace_setoptions);
835 return;
836 }
837 error_msg("Test for PTRACE_O_TRACECLONE failed, "
838 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800839}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200840
841/*
842 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
843 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
844 * and then see whether it will stop with (SIGTRAP | 0x80).
845 *
846 * Use of this option enables correct handling of user-generated SIGTRAPs,
847 * and SIGTRAPs generated by special instructions such as int3 on x86:
848 * _start: .globl _start
849 * int3
850 * movl $42, %ebx
851 * movl $1, %eax
852 * int $0x80
853 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
854 */
855static void
856test_ptrace_setoptions_for_all(void)
857{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000858 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
859 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200860 int pid;
861 int it_worked = 0;
862
863 pid = fork();
864 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200865 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200866
867 if (pid == 0) {
868 pid = getpid();
869 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200870 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000871 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
872 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200873 kill(pid, SIGSTOP);
874 _exit(0); /* parent should see entry into this syscall */
875 }
876
877 while (1) {
878 int status, tracee_pid;
879
880 errno = 0;
881 tracee_pid = wait(&status);
882 if (tracee_pid <= 0) {
883 if (errno == EINTR)
884 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000885 kill_save_errno(pid, SIGKILL);
886 perror_msg_and_die("%s: unexpected wait result %d",
887 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200888 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200889 if (WIFEXITED(status)) {
890 if (WEXITSTATUS(status) == 0)
891 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000892 error_msg_and_die("%s: unexpected exit status %u",
893 __func__, WEXITSTATUS(status));
894 }
895 if (WIFSIGNALED(status)) {
896 error_msg_and_die("%s: unexpected signal %u",
897 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200898 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200899 if (!WIFSTOPPED(status)) {
900 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000901 error_msg_and_die("%s: unexpected wait status %x",
902 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200903 }
904 if (WSTOPSIG(status) == SIGSTOP) {
905 /*
906 * We don't check "options aren't accepted" error.
907 * If it happens, we'll never get (SIGTRAP | 0x80),
908 * and thus will decide to not use the option.
909 * IOW: the outcome of the test will be correct.
910 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000911 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
912 && errno != EINVAL && errno != EIO)
913 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200914 }
915 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
916 it_worked = 1;
917 }
918 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000919 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200920 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200921 }
922 }
923
924 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200925 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200926 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200927 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200928 fprintf(stderr, "ptrace_setoptions = %#x\n",
929 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200930 return;
931 }
932
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000933 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
934 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200935}
Wang Chaob13c0de2010-11-12 17:25:19 +0800936#endif
937
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000939main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 struct tcb *tcp;
942 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000943 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 struct sigaction sa;
945
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000946 progname = argv[0] ? argv[0] : "strace";
947
Denys Vlasenko75422762011-05-27 14:36:01 +0200948 strace_tracer_pid = getpid();
949
Roland McGrathee9d4352002-12-18 04:16:10 +0000950 /* Allocate the initial tcbtab. */
951 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200952 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200953 if (!tcbtab)
954 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200955 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200956 if (!tcp)
957 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200958 for (c = 0; c < tcbtabsize; c++)
959 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000960
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000961 outf = stderr;
962 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000963 set_sortby(DEFAULT_SORTBY);
964 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 qualify("trace=all");
966 qualify("abbrev=all");
967 qualify("verbose=all");
968 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000970 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000971#ifndef USE_PROCFS
972 "D"
973#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000974 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 switch (c) {
976 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000977 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200978 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000979 }
980 cflag = CFLAG_ONLY_STATS;
981 break;
982 case 'C':
983 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200984 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000985 }
986 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 break;
988 case 'd':
989 debug++;
990 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000991#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000992 case 'D':
993 daemonized_tracer = 1;
994 break;
995#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000996 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000997 optF = 1;
998 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 case 'f':
1000 followfork++;
1001 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 case 'h':
1003 usage(stdout, 0);
1004 break;
1005 case 'i':
1006 iflag++;
1007 break;
1008 case 'q':
1009 qflag++;
1010 break;
1011 case 'r':
1012 rflag++;
1013 tflag++;
1014 break;
1015 case 't':
1016 tflag++;
1017 break;
1018 case 'T':
1019 dtime++;
1020 break;
1021 case 'x':
1022 xflag++;
1023 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001024 case 'y':
1025 show_fd_path = 1;
1026 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 case 'v':
1028 qualify("abbrev=none");
1029 break;
1030 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001031 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 exit(0);
1033 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001034 case 'z':
1035 not_failing_only = 1;
1036 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 case 'a':
1038 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001039 if (acolumn < 0)
1040 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 break;
1042 case 'e':
1043 qualify(optarg);
1044 break;
1045 case 'o':
1046 outfname = strdup(optarg);
1047 break;
1048 case 'O':
1049 set_overhead(atoi(optarg));
1050 break;
1051 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001052 pid = atoi(optarg);
1053 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001054 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 break;
1056 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001057 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001058 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 break;
1060 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001061 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 tcp->flags |= TCB_ATTACHED;
1063 pflag_seen++;
1064 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001065 case 'P':
1066 tracing_paths = 1;
1067 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001068 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001069 }
1070 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 case 's':
1072 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001073 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001074 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001075 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 break;
1077 case 'S':
1078 set_sortby(optarg);
1079 break;
1080 case 'u':
1081 username = strdup(optarg);
1082 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001083 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001084 if (putenv(optarg) < 0)
1085 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001086 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 default:
1088 usage(stderr, 1);
1089 break;
1090 }
1091 }
1092
Denys Vlasenko102ec492011-08-25 01:27:59 +02001093 acolumn_spaces = malloc(acolumn + 1);
1094 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001095 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001096 memset(acolumn_spaces, ' ', acolumn);
1097 acolumn_spaces[acolumn] = '\0';
1098
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001099 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001100 usage(stderr, 1);
1101
Wang Chaod322a4b2010-08-05 14:30:11 +08001102 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001103 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001104 }
1105
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001106 if (!followfork)
1107 followfork = optF;
1108
Roland McGrathcb9def62006-04-25 07:48:03 +00001109 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001110 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001111 }
1112
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 /* See if they want to run as another user. */
1114 if (username != NULL) {
1115 struct passwd *pent;
1116
1117 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001118 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001120 pent = getpwnam(username);
1121 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001122 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 }
1124 run_uid = pent->pw_uid;
1125 run_gid = pent->pw_gid;
1126 }
1127 else {
1128 run_uid = getuid();
1129 run_gid = getgid();
1130 }
1131
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001132#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001133 if (followfork)
1134 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001135 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001136#endif
1137
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 /* Check if they want to redirect the output. */
1139 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001140 /* See if they want to pipe the output. */
1141 if (outfname[0] == '|' || outfname[0] == '!') {
1142 /*
1143 * We can't do the <outfname>.PID funny business
1144 * when using popen, so prohibit it.
1145 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001146 if (followfork > 1)
1147 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1148 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001149 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001150 else if (followfork <= 1)
1151 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 }
1153
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001154 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1155 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001157 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001158 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001161 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001162
Roland McGrath54cc1c82007-11-03 23:34:11 +00001163 /* Valid states here:
1164 optind < argc pflag_seen outfname interactive
1165 1 0 0 1
1166 0 1 0 1
1167 1 0 1 0
1168 0 1 1 1
1169 */
1170
1171 /* STARTUP_CHILD must be called before the signal handlers get
1172 installed below as they are inherited into the spawned process.
1173 Also we do not need to be protected by them as during interruption
1174 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1175 if (!pflag_seen)
1176 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 sigemptyset(&empty_set);
1179 sigemptyset(&blocked_set);
1180 sa.sa_handler = SIG_IGN;
1181 sigemptyset(&sa.sa_mask);
1182 sa.sa_flags = 0;
1183 sigaction(SIGTTOU, &sa, NULL);
1184 sigaction(SIGTTIN, &sa, NULL);
1185 if (interactive) {
1186 sigaddset(&blocked_set, SIGHUP);
1187 sigaddset(&blocked_set, SIGINT);
1188 sigaddset(&blocked_set, SIGQUIT);
1189 sigaddset(&blocked_set, SIGPIPE);
1190 sigaddset(&blocked_set, SIGTERM);
1191 sa.sa_handler = interrupt;
1192#ifdef SUNOS4
1193 /* POSIX signals on sunos4.1 are a little broken. */
1194 sa.sa_flags = SA_INTERRUPT;
1195#endif /* SUNOS4 */
1196 }
1197 sigaction(SIGHUP, &sa, NULL);
1198 sigaction(SIGINT, &sa, NULL);
1199 sigaction(SIGQUIT, &sa, NULL);
1200 sigaction(SIGPIPE, &sa, NULL);
1201 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001202#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203 sa.sa_handler = reaper;
1204 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001205#else
1206 /* Make sure SIGCHLD has the default action so that waitpid
1207 definitely works without losing track of children. The user
1208 should not have given us a bogus state to inherit, but he might
1209 have. Arguably we should detect SIG_IGN here and pass it on
1210 to children, but probably noone really needs that. */
1211 sa.sa_handler = SIG_DFL;
1212 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001213#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001215 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001216 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001217
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218 if (trace() < 0)
1219 exit(1);
1220 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001221 fflush(NULL);
1222 if (exit_code > 0xff) {
1223 /* Child was killed by a signal, mimic that. */
1224 exit_code &= 0xff;
1225 signal(exit_code, SIG_DFL);
1226 raise(exit_code);
1227 /* Paranoia - what if this signal is not fatal?
1228 Exit with 128 + signo then. */
1229 exit_code += 128;
1230 }
1231 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001232}
1233
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001234static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001235expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001236{
1237 /* Allocate some more TCBs and expand the table.
1238 We don't want to relocate the TCBs because our
1239 callers have pointers and it would be a pain.
1240 So tcbtab is a table of pointers. Since we never
1241 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001242 int i = tcbtabsize;
1243 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1244 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001245 if (!newtab || !newtcbs)
1246 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001247 tcbtabsize *= 2;
1248 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001249 while (i < tcbtabsize)
1250 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001251}
1252
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001254alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255{
1256 int i;
1257 struct tcb *tcp;
1258
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001259 if (nprocs == tcbtabsize)
1260 expand_tcbtab();
1261
Roland McGrathee9d4352002-12-18 04:16:10 +00001262 for (i = 0; i < tcbtabsize; i++) {
1263 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001265 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001267 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268 tcp->outf = outf; /* Initialise to current out file */
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001269#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001271#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001273 if (debug)
1274 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001275 if (command_options_parsed)
1276 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001277 return tcp;
1278 }
1279 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001280 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281}
1282
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001283#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001285proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286{
1287 char proc[32];
1288 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001289#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001290 int i;
1291 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 sigset_t signals;
1293 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001294#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295#ifndef HAVE_POLLABLE_PROCFS
1296 static int last_pfd;
1297#endif
1298
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001299#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001300 /* Open the process pseudo-files in /proc. */
1301 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001302 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1303 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 perror("strace: open(\"/proc/...\", ...)");
1305 return -1;
1306 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001307 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001308 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001309 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1310 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001311 perror("strace: open(\"/proc/...\", ...)");
1312 return -1;
1313 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001314 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001315 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001316 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1317 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001318 perror("strace: open(\"/proc/...\", ...)");
1319 return -1;
1320 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001321 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001322#else
1323 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001324# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001325 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001326 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001327# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001328 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001329 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001330# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001331 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001332 perror("strace: open(\"/proc/...\", ...)");
1333 return -1;
1334 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001335 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001336#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337#ifdef FREEBSD
1338 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001339 tcp->pfd_reg = open(proc, O_RDONLY);
1340 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001341 perror("strace: open(\"/proc/.../regs\", ...)");
1342 return -1;
1343 }
1344 if (cflag) {
1345 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001346 tcp->pfd_status = open(proc, O_RDONLY);
1347 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001348 perror("strace: open(\"/proc/.../status\", ...)");
1349 return -1;
1350 }
1351 } else
1352 tcp->pfd_status = -1;
1353#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001354 rebuild_pollv();
1355 if (!attaching) {
1356 /*
1357 * Wait for the child to pause. Because of a race
1358 * condition we have to poll for the event.
1359 */
1360 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001361 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001362 perror("strace: PIOCSTATUS");
1363 return -1;
1364 }
1365 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001366 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001367 }
1368 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001369#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001370 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001371 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001372 perror("strace: PIOCSTOP");
1373 return -1;
1374 }
Roland McGrath553a6092002-12-16 20:40:39 +00001375#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376#ifdef PIOCSET
1377 /* Set Run-on-Last-Close. */
1378 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001379 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380 perror("PIOCSET PR_RLC");
1381 return -1;
1382 }
1383 /* Set or Reset Inherit-on-Fork. */
1384 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001385 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 perror("PIOC{SET,RESET} PR_FORK");
1387 return -1;
1388 }
1389#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001390#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1392 perror("PIOCSRLC");
1393 return -1;
1394 }
1395 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1396 perror("PIOC{S,R}FORK");
1397 return -1;
1398 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001399#else /* FREEBSD */
1400 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1401 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1402 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001403 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001404 }
1405 arg &= ~PF_LINGER;
1406 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001407 perror("PIOCSFL");
1408 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001409 }
1410#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001412#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001413 /* Enable all syscall entries we care about. */
1414 premptyset(&syscalls);
1415 for (i = 1; i < MAX_QUALS; ++i) {
1416 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001417 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001418 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001419 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001420 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001421 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001422#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001423 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001424#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001425#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001426 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001427#endif
1428#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001429 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001430#endif
1431#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001432 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001433#endif
1434 }
1435 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 perror("PIOCSENTRY");
1437 return -1;
1438 }
John Hughes19e49982001-10-19 08:59:12 +00001439 /* Enable the syscall exits. */
1440 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441 perror("PIOSEXIT");
1442 return -1;
1443 }
John Hughes19e49982001-10-19 08:59:12 +00001444 /* Enable signals we care about. */
1445 premptyset(&signals);
1446 for (i = 1; i < MAX_QUALS; ++i) {
1447 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001448 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001449 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001450 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 perror("PIOCSTRACE");
1452 return -1;
1453 }
John Hughes19e49982001-10-19 08:59:12 +00001454 /* Enable faults we care about */
1455 premptyset(&faults);
1456 for (i = 1; i < MAX_QUALS; ++i) {
1457 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001458 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001459 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001460 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 perror("PIOCSFAULT");
1462 return -1;
1463 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001464#else /* FREEBSD */
1465 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001466 arg = S_SIG | S_SCE | S_SCX;
1467 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001468 perror("PIOCBIS");
1469 return -1;
1470 }
1471#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472 if (!attaching) {
1473#ifdef MIPS
1474 /*
1475 * The SGI PRSABORT doesn't work for pause() so
1476 * we send it a caught signal to wake it up.
1477 */
1478 kill(tcp->pid, SIGINT);
1479#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001480#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001482 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001483 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484 perror("PIOCRUN");
1485 return -1;
1486 }
Roland McGrath553a6092002-12-16 20:40:39 +00001487#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001488#endif /* !MIPS*/
1489#ifdef FREEBSD
1490 /* wake up the child if it received the SIGSTOP */
1491 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001492#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493 for (;;) {
1494 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001495 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496 perror("PIOCWSTOP");
1497 return -1;
1498 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001499 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001500 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001501 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001502 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 break;
1504 }
1505 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001506#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001507 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001508 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1509#else
1510 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1511#endif
1512 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 perror("PIOCRUN");
1514 return -1;
1515 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001516#ifdef FREEBSD
1517 /* handle the case where we "opened" the child before
1518 it did the kill -STOP */
1519 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1520 tcp->status.PR_WHAT == SIGSTOP)
1521 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001522#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 }
1524 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001525#ifdef FREEBSD
1526 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001527 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001528 /* We are attaching to an already running process.
1529 * Try to figure out the state of the process in syscalls,
1530 * to handle the first event well.
1531 * This is done by having a look at the "wchan" property of the
1532 * process, which tells where it is stopped (if it is). */
1533 FILE * status;
1534 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001535
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001536 sprintf(proc, "/proc/%d/status", tcp->pid);
1537 status = fopen(proc, "r");
1538 if (status &&
1539 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1540 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1541 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1542 strcmp(wchan, "stopevent")) {
1543 /* The process is asleep in the middle of a syscall.
1544 Fake the syscall entry event */
1545 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1546 tcp->status.PR_WHY = PR_SYSENTRY;
1547 trace_syscall(tcp);
1548 }
1549 if (status)
1550 fclose(status);
1551 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001552 }
1553#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554#ifndef HAVE_POLLABLE_PROCFS
1555 if (proc_poll_pipe[0] != -1)
1556 proc_poller(tcp->pfd);
1557 else if (nprocs > 1) {
1558 proc_poll_open();
1559 proc_poller(last_pfd);
1560 proc_poller(tcp->pfd);
1561 }
1562 last_pfd = tcp->pfd;
1563#endif /* !HAVE_POLLABLE_PROCFS */
1564 return 0;
1565}
1566
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001567#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001569struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001570pid2tcb(int pid)
1571{
1572 int i;
1573
1574 if (pid <= 0)
1575 return NULL;
1576
1577 for (i = 0; i < tcbtabsize; i++) {
1578 struct tcb *tcp = tcbtab[i];
1579 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1580 return tcp;
1581 }
1582
1583 return NULL;
1584}
1585
1586#ifdef USE_PROCFS
1587
1588static struct tcb *
1589first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590{
1591 int i;
1592 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001593 for (i = 0; i < tcbtabsize; i++) {
1594 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001595 if (tcp->flags & TCB_INUSE)
1596 return tcp;
1597 }
1598 return NULL;
1599}
1600
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001602pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603{
1604 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605
Roland McGrathca16be82003-01-10 19:55:28 +00001606 for (i = 0; i < tcbtabsize; i++) {
1607 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 if (tcp->pfd != pfd)
1609 continue;
1610 if (tcp->flags & TCB_INUSE)
1611 return tcp;
1612 }
1613 return NULL;
1614}
1615
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001616#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617
1618void
Denys Vlasenko12014262011-05-30 14:00:14 +02001619droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620{
1621 if (tcp->pid == 0)
1622 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001623
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001625 if (debug)
1626 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001627
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001628#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629 if (tcp->pfd != -1) {
1630 close(tcp->pfd);
1631 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001632# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001633 if (tcp->pfd_reg != -1) {
1634 close(tcp->pfd_reg);
1635 tcp->pfd_reg = -1;
1636 }
1637 if (tcp->pfd_status != -1) {
1638 close(tcp->pfd_status);
1639 tcp->pfd_status = -1;
1640 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001641# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001642 tcp->flags = 0; /* rebuild_pollv needs it */
1643 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001645#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001646
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001647 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001649
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001650 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651}
1652
Roland McGrath0a463882007-07-05 18:43:16 +00001653/* detach traced process; continue with sig
1654 Never call DETACH twice on the same process as both unattached and
1655 attached-unstopped processes give the same ESRCH. For unattached process we
1656 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657
1658static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001659detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660{
1661 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001662#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001663 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001664#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665
1666 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001667 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668
1669#ifdef LINUX
1670 /*
1671 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001672 * before detaching. Arghh. We go through hoops
1673 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001675#if defined(SPARC)
1676#undef PTRACE_DETACH
1677#define PTRACE_DETACH PTRACE_SUNDETACH
1678#endif
Roland McGrath02203312007-06-11 22:06:31 +00001679 /*
1680 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1681 * expected SIGSTOP. We must catch exactly one as otherwise the
1682 * detached process would be left stopped (process state T).
1683 */
1684 catch_sigstop = (tcp->flags & TCB_STARTUP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001685 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1686 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001688 }
1689 else if (errno != ESRCH) {
1690 /* Shouldn't happen. */
1691 perror("detach: ptrace(PTRACE_DETACH, ...)");
1692 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001693 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001694 if (errno != ESRCH)
1695 perror("detach: checking sanity");
1696 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001697 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001698 if (errno != ESRCH)
1699 perror("detach: stopping child");
1700 }
Roland McGrath02203312007-06-11 22:06:31 +00001701 else
1702 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001703 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001705#ifdef __WALL
1706 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1707 if (errno == ECHILD) /* Already gone. */
1708 break;
1709 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001710 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001711 break;
1712 }
1713#endif /* __WALL */
1714 /* No __WALL here. */
1715 if (waitpid(tcp->pid, &status, 0) < 0) {
1716 if (errno != ECHILD) {
1717 perror("detach: waiting");
1718 break;
1719 }
1720#ifdef __WCLONE
1721 /* If no processes, try clones. */
1722 if (wait4(tcp->pid, &status, __WCLONE,
1723 NULL) < 0) {
1724 if (errno != ECHILD)
1725 perror("detach: waiting");
1726 break;
1727 }
1728#endif /* __WCLONE */
1729 }
1730#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001731 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001732#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733 if (!WIFSTOPPED(status)) {
1734 /* Au revoir, mon ami. */
1735 break;
1736 }
1737 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001738 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 break;
1740 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001741 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001742 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001743 : WSTOPSIG(status));
1744 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001747 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001748#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749
1750#if defined(SUNOS4)
1751 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1752 if (sig && kill(tcp->pid, sig) < 0)
1753 perror("detach: kill");
1754 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001755 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756#endif /* SUNOS4 */
1757
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758 if (!qflag)
1759 fprintf(stderr, "Process %u detached\n", tcp->pid);
1760
1761 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001762
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 return error;
1764}
1765
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001766#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001768static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769{
1770 int pid;
1771 int status;
1772
1773 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 }
1775}
1776
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001777#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778
1779static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001780cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781{
1782 int i;
1783 struct tcb *tcp;
1784
Roland McGrathee9d4352002-12-18 04:16:10 +00001785 for (i = 0; i < tcbtabsize; i++) {
1786 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 if (!(tcp->flags & TCB_INUSE))
1788 continue;
1789 if (debug)
1790 fprintf(stderr,
1791 "cleanup: looking at pid %u\n", tcp->pid);
1792 if (tcp_last &&
1793 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001794 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001795 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796 }
1797 if (tcp->flags & TCB_ATTACHED)
1798 detach(tcp, 0);
1799 else {
1800 kill(tcp->pid, SIGCONT);
1801 kill(tcp->pid, SIGTERM);
1802 }
1803 }
1804 if (cflag)
1805 call_summary(outf);
1806}
1807
1808static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001809interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810{
1811 interrupted = 1;
1812}
1813
1814#ifndef HAVE_STRERROR
1815
Roland McGrath6d2b3492002-12-30 00:51:30 +00001816#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817extern int sys_nerr;
1818extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001819#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820
1821const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001822strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823{
1824 static char buf[64];
1825
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001826 if (err_no < 1 || err_no >= sys_nerr) {
1827 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828 return buf;
1829 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001830 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001831}
1832
1833#endif /* HAVE_STERRROR */
1834
1835#ifndef HAVE_STRSIGNAL
1836
Roland McGrath8f474e02003-01-14 07:53:33 +00001837#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001838extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001840#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1841extern char *_sys_siglist[];
1842#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843
1844const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001845strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846{
1847 static char buf[64];
1848
1849 if (sig < 1 || sig >= NSIG) {
1850 sprintf(buf, "Unknown signal %d", sig);
1851 return buf;
1852 }
1853#ifdef HAVE__SYS_SIGLIST
1854 return _sys_siglist[sig];
1855#else
1856 return sys_siglist[sig];
1857#endif
1858}
1859
1860#endif /* HAVE_STRSIGNAL */
1861
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001862#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001863
1864static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001865rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866{
1867 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001869 free(pollv);
1870 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001871 if (!pollv)
1872 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001873
Roland McGrathca16be82003-01-10 19:55:28 +00001874 for (i = j = 0; i < tcbtabsize; i++) {
1875 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876 if (!(tcp->flags & TCB_INUSE))
1877 continue;
1878 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001879 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 j++;
1881 }
1882 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001883 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884 }
1885}
1886
1887#ifndef HAVE_POLLABLE_PROCFS
1888
1889static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001890proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001891{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001892 int i;
1893
1894 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001895 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 }
1897 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001898 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 }
1900}
1901
1902static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001903proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904{
1905 int i;
1906 int n;
1907 struct proc_pollfd pollinfo;
1908
Denys Vlasenko5d645812011-08-20 12:48:18 +02001909 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1910 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 return n;
1912 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001913 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 }
1915 for (i = 0; i < nprocs; i++) {
1916 if (pollv[i].fd == pollinfo.fd)
1917 pollv[i].revents = pollinfo.revents;
1918 else
1919 pollv[i].revents = 0;
1920 }
1921 poller_pid = pollinfo.pid;
1922 return 1;
1923}
1924
1925static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001926wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927{
1928}
1929
1930static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001931proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932{
1933 struct proc_pollfd pollinfo;
1934 struct sigaction sa;
1935 sigset_t blocked_set, empty_set;
1936 int i;
1937 int n;
1938 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001939#ifdef FREEBSD
1940 struct procfs_status pfs;
1941#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942
1943 switch (fork()) {
1944 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001945 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946 case 0:
1947 break;
1948 default:
1949 return;
1950 }
1951
1952 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1953 sa.sa_flags = 0;
1954 sigemptyset(&sa.sa_mask);
1955 sigaction(SIGHUP, &sa, NULL);
1956 sigaction(SIGINT, &sa, NULL);
1957 sigaction(SIGQUIT, &sa, NULL);
1958 sigaction(SIGPIPE, &sa, NULL);
1959 sigaction(SIGTERM, &sa, NULL);
1960 sa.sa_handler = wakeup_handler;
1961 sigaction(SIGUSR1, &sa, NULL);
1962 sigemptyset(&blocked_set);
1963 sigaddset(&blocked_set, SIGUSR1);
1964 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1965 sigemptyset(&empty_set);
1966
1967 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001968 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 }
1970 n = rl.rlim_cur;
1971 for (i = 0; i < n; i++) {
1972 if (i != pfd && i != proc_poll_pipe[1])
1973 close(i);
1974 }
1975
1976 pollinfo.fd = pfd;
1977 pollinfo.pid = getpid();
1978 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001979#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001980 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1981#else
1982 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1983#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001984 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985 switch (errno) {
1986 case EINTR:
1987 continue;
1988 case EBADF:
1989 pollinfo.revents = POLLERR;
1990 break;
1991 case ENOENT:
1992 pollinfo.revents = POLLHUP;
1993 break;
1994 default:
1995 perror("proc_poller: PIOCWSTOP");
1996 }
1997 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1998 _exit(0);
1999 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002000 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2002 sigsuspend(&empty_set);
2003 }
2004}
2005
2006#endif /* !HAVE_POLLABLE_PROCFS */
2007
2008static int
2009choose_pfd()
2010{
2011 int i, j;
2012 struct tcb *tcp;
2013
2014 static int last;
2015
2016 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002017 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002018 /*
2019 * The previous process is ready to run again. We'll
2020 * let it do so if it is currently in a syscall. This
2021 * heuristic improves the readability of the trace.
2022 */
2023 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002024 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 return pollv[last].fd;
2026 }
2027
2028 for (i = 0; i < nprocs; i++) {
2029 /* Let competing children run round robin. */
2030 j = (i + last + 1) % nprocs;
2031 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2032 tcp = pfd2tcb(pollv[j].fd);
2033 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002034 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 }
2036 droptcb(tcp);
2037 return -1;
2038 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002039 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 last = j;
2041 return pollv[j].fd;
2042 }
2043 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002044 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045}
2046
2047static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002048trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002050#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002051 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002052#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 struct tcb *tcp;
2054 int pfd;
2055 int what;
2056 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058
2059 for (;;) {
2060 if (interactive)
2061 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2062
2063 if (nprocs == 0)
2064 break;
2065
2066 switch (nprocs) {
2067 case 1:
2068#ifndef HAVE_POLLABLE_PROCFS
2069 if (proc_poll_pipe[0] == -1) {
2070#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002071 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002072 if (!tcp)
2073 continue;
2074 pfd = tcp->pfd;
2075 if (pfd == -1)
2076 continue;
2077 break;
2078#ifndef HAVE_POLLABLE_PROCFS
2079 }
2080 /* fall through ... */
2081#endif /* !HAVE_POLLABLE_PROCFS */
2082 default:
2083#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002084#ifdef POLL_HACK
2085 /* On some systems (e.g. UnixWare) we get too much ugly
2086 "unfinished..." stuff when multiple proceses are in
2087 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002088
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002089 if (in_syscall) {
2090 struct pollfd pv;
2091 tcp = in_syscall;
2092 in_syscall = NULL;
2093 pv.fd = tcp->pfd;
2094 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002095 what = poll(&pv, 1, 1);
2096 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002097 if (interrupted)
2098 return 0;
2099 continue;
2100 }
2101 else if (what == 1 && pv.revents & POLLWANT) {
2102 goto FOUND;
2103 }
2104 }
2105#endif
2106
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 if (poll(pollv, nprocs, INFTIM) < 0) {
2108 if (interrupted)
2109 return 0;
2110 continue;
2111 }
2112#else /* !HAVE_POLLABLE_PROCFS */
2113 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2114 if (interrupted)
2115 return 0;
2116 continue;
2117 }
2118#endif /* !HAVE_POLLABLE_PROCFS */
2119 pfd = choose_pfd();
2120 if (pfd == -1)
2121 continue;
2122 break;
2123 }
2124
2125 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002126 tcp = pfd2tcb(pfd);
2127 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002128 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129 }
John Hughesb6643082002-05-23 11:02:22 +00002130#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002131 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002132#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133 /* Get the status of the process. */
2134 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002135#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002136 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002137#else /* FREEBSD */
2138 /* Thanks to some scheduling mystery, the first poller
2139 sometimes waits for the already processed end of fork
2140 event. Doing a non blocking poll here solves the problem. */
2141 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002142 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002143 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002144 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002145#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 ioctl_errno = errno;
2147#ifndef HAVE_POLLABLE_PROCFS
2148 if (proc_poll_pipe[0] != -1) {
2149 if (ioctl_result < 0)
2150 kill(poller_pid, SIGKILL);
2151 else
2152 kill(poller_pid, SIGUSR1);
2153 }
2154#endif /* !HAVE_POLLABLE_PROCFS */
2155 }
2156 if (interrupted)
2157 return 0;
2158
2159 if (interactive)
2160 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2161
2162 if (ioctl_result < 0) {
2163 /* Find out what happened if it failed. */
2164 switch (ioctl_errno) {
2165 case EINTR:
2166 case EBADF:
2167 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002168#ifdef FREEBSD
2169 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002170#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 case ENOENT:
2172 droptcb(tcp);
2173 continue;
2174 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002175 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 }
2177 }
2178
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002179#ifdef FREEBSD
2180 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2181 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002182 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002183 continue;
2184 }
Roland McGrath553a6092002-12-16 20:40:39 +00002185#endif
2186
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 /* clear the just started flag */
2188 tcp->flags &= ~TCB_STARTUP;
2189
2190 /* set current output file */
2191 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002192 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002193
2194 if (cflag) {
2195 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002196#ifdef FREEBSD
2197 char buf[1024];
2198 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199
Denys Vlasenko5d645812011-08-20 12:48:18 +02002200 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2201 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002202 buf[len] = '\0';
2203 sscanf(buf,
2204 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2205 &stime.tv_sec, &stime.tv_usec);
2206 } else
2207 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002208#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2210 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002211#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2213 tcp->stime = stime;
2214 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002215 what = tcp->status.PR_WHAT;
2216 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002217#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002219 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2220 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002222 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002223 }
2224 }
2225 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002226#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002228#ifdef POLL_HACK
2229 in_syscall = tcp;
2230#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231 case PR_SYSEXIT:
2232 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002233 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 }
2235 break;
2236 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002237 if (cflag != CFLAG_ONLY_STATS
2238 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002239 printleader(tcp);
2240 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002241 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002242 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002243#ifdef PR_INFO
2244 if (tcp->status.PR_INFO.si_signo == what) {
2245 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002246 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002247 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002248 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002249 }
2250#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002251 }
2252 break;
2253 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002254 if (cflag != CFLAGS_ONLY_STATS
2255 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 printleader(tcp);
2257 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002258 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002259 }
2260 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002261#ifdef FREEBSD
2262 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002263 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002264#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002266 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267 break;
2268 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002269 /* Remember current print column before continuing. */
2270 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002271 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002272#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002273 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002274#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002275 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002276#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002277 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002278 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002279 }
2280 }
2281 return 0;
2282}
2283
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002284#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285
Roland McGratheb9e2e82009-06-02 16:49:22 -07002286static int
2287trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288{
2289 int pid;
2290 int wait_errno;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002291 int status, sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002292 struct tcb *tcp;
2293#ifdef LINUX
2294 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002295 struct rusage *rup = cflag ? &ru : NULL;
2296# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002297 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002298# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002299#endif /* LINUX */
2300
Roland McGratheb9e2e82009-06-02 16:49:22 -07002301 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002302 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002303 return 0;
2304 if (interactive)
2305 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002307# ifdef __WALL
2308 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002309 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002310 /* this kernel does not support __WALL */
2311 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002312 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002313 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002314 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002315 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002316 pid = wait4(-1, &status, __WCLONE, rup);
2317 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002318 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002319 }
2320 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002321# else
2322 pid = wait4(-1, &status, 0, rup);
2323# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324#endif /* LINUX */
2325#ifdef SUNOS4
2326 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002327#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002328 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002329 if (interactive)
2330 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002331
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002332 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002333 switch (wait_errno) {
2334 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002335 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002336 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337 /*
2338 * We would like to verify this case
2339 * but sometimes a race in Solbourne's
2340 * version of SunOS sometimes reports
2341 * ECHILD before sending us SIGCHILD.
2342 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002343 return 0;
2344 default:
2345 errno = wait_errno;
2346 perror("strace: wait");
2347 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348 }
2349 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002350 if (pid == popen_pid) {
2351 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002352 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002353 continue;
2354 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002355 if (debug) {
2356 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2357#ifdef LINUX
2358 unsigned ev = (unsigned)status >> 16;
2359 if (ev) {
2360 static const char *const event_names[] = {
2361 [PTRACE_EVENT_CLONE] = "CLONE",
2362 [PTRACE_EVENT_FORK] = "FORK",
2363 [PTRACE_EVENT_VFORK] = "VFORK",
2364 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2365 [PTRACE_EVENT_EXEC] = "EXEC",
2366 [PTRACE_EVENT_EXIT] = "EXIT",
2367 };
2368 const char *e;
2369 if (ev < ARRAY_SIZE(event_names))
2370 e = event_names[ev];
2371 else {
2372 sprintf(buf, "?? (%u)", ev);
2373 e = buf;
2374 }
2375 fprintf(stderr, " PTRACE_EVENT_%s", e);
2376 }
2377#endif
2378 strcpy(buf, "???");
2379 if (WIFSIGNALED(status))
2380#ifdef WCOREDUMP
2381 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2382 WCOREDUMP(status) ? "core," : "",
2383 signame(WTERMSIG(status)));
2384#else
2385 sprintf(buf, "WIFSIGNALED,sig=%s",
2386 signame(WTERMSIG(status)));
2387#endif
2388 if (WIFEXITED(status))
2389 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2390 if (WIFSTOPPED(status))
2391 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002392#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002393 if (WIFCONTINUED(status))
2394 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002395#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002396 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2397 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398
2399 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002400 tcp = pid2tcb(pid);
2401 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002402#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002403 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002404 /* This is needed to go with the CLONE_PTRACE
2405 changes in process.c/util.c: we might see
2406 the child's initial trap before we see the
2407 parent return from the clone syscall.
2408 Leave the child suspended until the parent
2409 returns from its system call. Only then
2410 will we have the association of parent and
2411 child so that we know how to do clearbpt
2412 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002413 tcp = alloctcb(pid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +02002414 tcp->flags |= TCB_ATTACHED | TCB_STARTUP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002415 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002416 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002417 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002418 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002419 else
2420 /* This can happen if a clone call used
2421 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002422#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002423 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002424 if (WIFSTOPPED(status))
2425 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002426 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002427 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002429 /* set current output file */
2430 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002431 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002432#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002433 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2435 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002436 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002437#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002438
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002439 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002440 if (pid == strace_child)
2441 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002442 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2444 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002445#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002446 tprintf("+++ killed by %s %s+++",
2447 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002448 WCOREDUMP(status) ? "(core dumped) " : "");
2449#else
2450 tprintf("+++ killed by %s +++",
2451 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002452#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002453 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 }
2455 droptcb(tcp);
2456 continue;
2457 }
2458 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002459 if (pid == strace_child)
2460 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002461 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002462 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002463 tprintf(" <unfinished ... exit status %d>\n",
2464 WEXITSTATUS(status));
2465 tcp_last = NULL;
2466 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002467 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2468 printleader(tcp);
2469 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2470 printtrailer();
2471 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 droptcb(tcp);
2473 continue;
2474 }
2475 if (!WIFSTOPPED(status)) {
2476 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2477 droptcb(tcp);
2478 continue;
2479 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002481 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002482 /* Ptrace event (we ignore all of them for now) */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002483 goto restart_tracee_with_sig_0;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002484 }
2485
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002486 sig = WSTOPSIG(status);
2487
Roland McGrath02203312007-06-11 22:06:31 +00002488 /*
2489 * Interestingly, the process may stop
2490 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002491 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002492 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002493 * A no-MMU vforked child won't send up a signal,
2494 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002495 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002496 if ((tcp->flags & TCB_STARTUP) &&
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002497 (sig == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002498 /*
2499 * This flag is there to keep us in sync.
2500 * Next time this process stops it should
2501 * really be entering a system call.
2502 */
2503 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002504 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002505 /*
2506 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002507 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002508 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002509 if (clearbpt(tcp) < 0) {
2510 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002511 droptcb(tcp);
2512 cleanup();
2513 return -1;
2514 }
2515 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002516#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002517 if (ptrace_setoptions) {
2518 if (debug)
2519 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2520 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2521 if (errno != ESRCH) {
2522 /* Should never happen, really */
2523 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002524 }
2525 }
2526 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002527#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002528 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002529 }
2530
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002531 if (sig != syscall_trap_sig) {
2532 if (sig == SIGSTOP &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 (tcp->flags & TCB_SIGTRAPPED)) {
2534 /*
2535 * Trapped attempt to block SIGTRAP
2536 * Hope we are back in control now.
2537 */
2538 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002539 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002541 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002542 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002543 siginfo_t si;
2544#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002545 long pc = 0;
2546 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002547
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002548 upeek(tcp, PT_CR_IPSR, &psr);
2549 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002550
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002551# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002552 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002553# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002554# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002555#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002556# define PC_FORMAT_STR ""
2557# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002558#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002559 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002560 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002561 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002562 printsiginfo(&si, verbose(tcp));
2563 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002564 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002565 PC_FORMAT_ARG);
2566 } else
2567 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002568 strsignal(sig),
2569 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002570 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002571 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002573 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002574 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002575
2576 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002577 if (interrupted)
2578 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002579
2580 /* This should be syscall entry or exit.
2581 * (Or it still can be that pesky post-execve SIGTRAP!)
2582 * Handle it.
2583 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002584 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2585 /* ptrace() failed in trace_syscall() with ESRCH.
2586 * Likely a result of process disappearing mid-flight.
2587 * Observed case: exit_group() terminating
2588 * all processes in thread group. In this case, threads
2589 * "disappear" in an unpredictable moment without any
2590 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002591 */
2592 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002593 if (tcp_last) {
2594 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002595 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002596 */
2597 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002598 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002599 printtrailer();
2600 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002601 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002602 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002603 ptrace(PTRACE_KILL,
2604 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 droptcb(tcp);
2606 }
2607 continue;
2608 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002609 restart_tracee_with_sig_0:
2610 sig = 0;
2611 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002612 /* Remember current print column before continuing. */
2613 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002614 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615 cleanup();
2616 return -1;
2617 }
2618 }
2619 return 0;
2620}
2621
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002622#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002623
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002624void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002626{
2627 va_list args;
2628
Andreas Schwabe5355de2009-10-27 16:56:43 +01002629 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002630 if (outf) {
2631 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002632 if (n < 0) {
2633 if (outf != stderr)
2634 perror(outfname == NULL
2635 ? "<writing to pipe>" : outfname);
2636 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002637 curcol += n;
2638 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002639 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002640}
2641
2642void
2643tprints(const char *str)
2644{
2645 if (outf) {
2646 int n = fputs(str, outf);
2647 if (n >= 0) {
2648 curcol += strlen(str);
2649 return;
2650 }
2651 if (outf != stderr)
2652 perror(outfname == NULL
2653 ? "<writing to pipe>" : outfname);
2654 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002655}
2656
2657void
Denys Vlasenko12014262011-05-30 14:00:14 +02002658printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002659{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002660 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002661 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002662 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002663 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002664 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002665 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002666 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002667 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002668 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002669 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002670 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002671 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002672 }
2673 curcol = 0;
2674 if ((followfork == 1 || pflag_seen > 1) && outfname)
2675 tprintf("%-5d ", tcp->pid);
2676 else if (nprocs > 1 && !outfname)
2677 tprintf("[pid %5u] ", tcp->pid);
2678 if (tflag) {
2679 char str[sizeof("HH:MM:SS")];
2680 struct timeval tv, dtv;
2681 static struct timeval otv;
2682
2683 gettimeofday(&tv, NULL);
2684 if (rflag) {
2685 if (otv.tv_sec == 0)
2686 otv = tv;
2687 tv_sub(&dtv, &tv, &otv);
2688 tprintf("%6ld.%06ld ",
2689 (long) dtv.tv_sec, (long) dtv.tv_usec);
2690 otv = tv;
2691 }
2692 else if (tflag > 2) {
2693 tprintf("%ld.%06ld ",
2694 (long) tv.tv_sec, (long) tv.tv_usec);
2695 }
2696 else {
2697 time_t local = tv.tv_sec;
2698 strftime(str, sizeof(str), "%T", localtime(&local));
2699 if (tflag > 1)
2700 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2701 else
2702 tprintf("%s ", str);
2703 }
2704 }
2705 if (iflag)
2706 printcall(tcp);
2707}
2708
2709void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002710tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002712 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002713 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002714}
2715
2716void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002717printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002718{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002719 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002720 tcp_last = NULL;
2721}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002722
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002723#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002724
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002725int
2726mp_ioctl(int fd, int cmd, void *arg, int size)
2727{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002728 struct iovec iov[2];
2729 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002730
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002731 iov[0].iov_base = &cmd;
2732 iov[0].iov_len = sizeof cmd;
2733 if (arg) {
2734 ++n;
2735 iov[1].iov_base = arg;
2736 iov[1].iov_len = size;
2737 }
Roland McGrath553a6092002-12-16 20:40:39 +00002738
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002739 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002740}
2741
2742#endif