blob: 2e963059de8c7212a3a13587ab9a6077826dbcc5 [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 Vlasenkof88837a2011-09-05 14:05:46 +0200494 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
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 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200515 if (!(tcp->flags & TCB_STARTUP)) {
516 /* -p PID, we failed to attach to PID itself
517 * but did attach to some of its sibling threads.
518 * Drop PID's tcp.
519 */
520 droptcb(tcp);
521 }
Roland McGrath02203312007-06-11 22:06:31 +0000522 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000523 } /* if (opendir worked) */
524 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200525# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000526 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
527 perror("attach: ptrace(PTRACE_ATTACH, ...)");
528 droptcb(tcp);
529 continue;
530 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200531 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200532 if (debug)
533 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000534
535 if (daemonized_tracer) {
536 /*
537 * It is our grandparent we trace, not a -p PID.
538 * Don't want to just detach on exit, so...
539 */
540 tcp->flags &= ~TCB_ATTACHED;
541 /*
542 * Make parent go away.
543 * Also makes grandparent's wait() unblock.
544 */
545 kill(getppid(), SIGKILL);
546 }
547
Roland McGrath02203312007-06-11 22:06:31 +0000548#endif /* !USE_PROCFS */
549 if (!qflag)
550 fprintf(stderr,
551 "Process %u attached - interrupt to quit\n",
552 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200553 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000554
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200555 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000556 if (interactive)
557 sigprocmask(SIG_SETMASK, &empty_set, NULL);
558}
559
560static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200561startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000562{
563 struct stat statbuf;
564 const char *filename;
565 char pathname[MAXPATHLEN];
566 int pid = 0;
567 struct tcb *tcp;
568
569 filename = argv[0];
570 if (strchr(filename, '/')) {
571 if (strlen(filename) > sizeof pathname - 1) {
572 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200573 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000574 }
575 strcpy(pathname, filename);
576 }
577#ifdef USE_DEBUGGING_EXEC
578 /*
579 * Debuggers customarily check the current directory
580 * first regardless of the path but doing that gives
581 * security geeks a panic attack.
582 */
583 else if (stat(filename, &statbuf) == 0)
584 strcpy(pathname, filename);
585#endif /* USE_DEBUGGING_EXEC */
586 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000587 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000588 int m, n, len;
589
590 for (path = getenv("PATH"); path && *path; path += m) {
591 if (strchr(path, ':')) {
592 n = strchr(path, ':') - path;
593 m = n + 1;
594 }
595 else
596 m = n = strlen(path);
597 if (n == 0) {
598 if (!getcwd(pathname, MAXPATHLEN))
599 continue;
600 len = strlen(pathname);
601 }
602 else if (n > sizeof pathname - 1)
603 continue;
604 else {
605 strncpy(pathname, path, n);
606 len = n;
607 }
608 if (len && pathname[len - 1] != '/')
609 pathname[len++] = '/';
610 strcpy(pathname + len, filename);
611 if (stat(pathname, &statbuf) == 0 &&
612 /* Accept only regular files
613 with some execute bits set.
614 XXX not perfect, might still fail */
615 S_ISREG(statbuf.st_mode) &&
616 (statbuf.st_mode & 0111))
617 break;
618 }
619 }
620 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200621 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000622 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000623 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000624 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200625 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000626 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200627 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
628 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000629 ) {
630 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200631 if (outf != stderr)
632 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000633#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200634# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000635 /* Kludge for SGI, see proc_open for details. */
636 sa.sa_handler = foobar;
637 sa.sa_flags = 0;
638 sigemptyset(&sa.sa_mask);
639 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200640# endif
641# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000642 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200643# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200644 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200645# endif
Roland McGrath02203312007-06-11 22:06:31 +0000646#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000647 if (!daemonized_tracer) {
648 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200649 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 }
651 if (debug)
652 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000653 }
Roland McGrath02203312007-06-11 22:06:31 +0000654
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200655 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000656 uid_t run_euid = run_uid;
657 gid_t run_egid = run_gid;
658
659 if (statbuf.st_mode & S_ISUID)
660 run_euid = statbuf.st_uid;
661 if (statbuf.st_mode & S_ISGID)
662 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000663 /*
664 * It is important to set groups before we
665 * lose privileges on setuid.
666 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200667 if (initgroups(username, run_gid) < 0) {
668 perror_msg_and_die("initgroups");
669 }
670 if (setregid(run_gid, run_egid) < 0) {
671 perror_msg_and_die("setregid");
672 }
673 if (setreuid(run_uid, run_euid) < 0) {
674 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000675 }
676 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200677 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000678 setreuid(run_uid, run_uid);
679
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000680 if (!daemonized_tracer) {
681 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200682 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200684 * the immediately following execve syscall.
685 * Can't do this on NOMMU systems, we are after
686 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000687 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400688 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200689 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000690 } else {
691 struct sigaction sv_sigchld;
692 sigaction(SIGCHLD, NULL, &sv_sigchld);
693 /*
694 * Make sure it is not SIG_IGN, otherwise wait
695 * will not block.
696 */
697 signal(SIGCHLD, SIG_DFL);
698 /*
699 * Wait for grandchild to attach to us.
700 * It kills child after that, and wait() unblocks.
701 */
702 alarm(3);
703 wait(NULL);
704 alarm(0);
705 sigaction(SIGCHLD, &sv_sigchld, NULL);
706 }
Roland McGrath02203312007-06-11 22:06:31 +0000707#endif /* !USE_PROCFS */
708
709 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200710 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000711 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000712
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200713 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200714
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200715 if (!daemonized_tracer) {
716 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200717 if (!strace_vforked)
718 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
719 else
720 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200721 }
722 else {
723 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
724 strace_tracer_pid = getpid();
725 /* The tracee is our parent: */
726 pid = getppid();
727 tcp = alloctcb(pid);
728 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000729 tcp->flags |= TCB_ATTACHED;
730 }
Roland McGrath02203312007-06-11 22:06:31 +0000731#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000732 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200733 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000734 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200735#endif
Roland McGrath02203312007-06-11 22:06:31 +0000736}
737
Wang Chaob13c0de2010-11-12 17:25:19 +0800738#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000739static void kill_save_errno(pid_t pid, int sig)
740{
741 int saved_errno = errno;
742
743 (void) kill(pid, sig);
744 errno = saved_errno;
745}
746
Wang Chaob13c0de2010-11-12 17:25:19 +0800747/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000748 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800749 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000750 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800751 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000752static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200753test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800754{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000755 int pid, expected_grandchild = 0, found_grandchild = 0;
756 const unsigned int test_options = PTRACE_O_TRACECLONE |
757 PTRACE_O_TRACEFORK |
758 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800759
Denys Vlasenko5d645812011-08-20 12:48:18 +0200760 pid = fork();
761 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000762 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200763 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000764 pid = getpid();
765 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
766 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
767 __func__);
768 kill(pid, SIGSTOP);
769 if (fork() < 0)
770 perror_msg_and_die("fork");
771 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800772 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000773
774 while (1) {
775 int status, tracee_pid;
776
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000777 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000778 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000779 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000780 if (errno == EINTR)
781 continue;
782 else if (errno == ECHILD)
783 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000784 kill_save_errno(pid, SIGKILL);
785 perror_msg_and_die("%s: unexpected wait result %d",
786 __func__, tracee_pid);
787 }
788 if (WIFEXITED(status)) {
789 if (WEXITSTATUS(status)) {
790 if (tracee_pid != pid)
791 kill_save_errno(pid, SIGKILL);
792 error_msg_and_die("%s: unexpected exit status %u",
793 __func__, WEXITSTATUS(status));
794 }
795 continue;
796 }
797 if (WIFSIGNALED(status)) {
798 if (tracee_pid != pid)
799 kill_save_errno(pid, SIGKILL);
800 error_msg_and_die("%s: unexpected signal %u",
801 __func__, WTERMSIG(status));
802 }
803 if (!WIFSTOPPED(status)) {
804 if (tracee_pid != pid)
805 kill_save_errno(tracee_pid, SIGKILL);
806 kill(pid, SIGKILL);
807 error_msg_and_die("%s: unexpected wait status %x",
808 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000809 }
810 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000811 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000812 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
813 kill_save_errno(tracee_pid, SIGKILL);
814 kill_save_errno(pid, SIGKILL);
815 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800816 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000817 continue;
818 }
819 switch (WSTOPSIG(status)) {
820 case SIGSTOP:
821 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
822 && errno != EINVAL && errno != EIO)
823 perror_msg("PTRACE_SETOPTIONS");
824 break;
825 case SIGTRAP:
826 if (status >> 16 == PTRACE_EVENT_FORK) {
827 long msg = 0;
828
829 if (ptrace(PTRACE_GETEVENTMSG, pid,
830 NULL, (long) &msg) == 0)
831 expected_grandchild = msg;
832 }
833 break;
834 }
835 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
836 kill_save_errno(pid, SIGKILL);
837 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800838 }
839 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000840 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200841 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000842 if (debug)
843 fprintf(stderr, "ptrace_setoptions = %#x\n",
844 ptrace_setoptions);
845 return;
846 }
847 error_msg("Test for PTRACE_O_TRACECLONE failed, "
848 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800849}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200850
851/*
852 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
853 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
854 * and then see whether it will stop with (SIGTRAP | 0x80).
855 *
856 * Use of this option enables correct handling of user-generated SIGTRAPs,
857 * and SIGTRAPs generated by special instructions such as int3 on x86:
858 * _start: .globl _start
859 * int3
860 * movl $42, %ebx
861 * movl $1, %eax
862 * int $0x80
863 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
864 */
865static void
866test_ptrace_setoptions_for_all(void)
867{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000868 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
869 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200870 int pid;
871 int it_worked = 0;
872
873 pid = fork();
874 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200875 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200876
877 if (pid == 0) {
878 pid = getpid();
879 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200880 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000881 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
882 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200883 kill(pid, SIGSTOP);
884 _exit(0); /* parent should see entry into this syscall */
885 }
886
887 while (1) {
888 int status, tracee_pid;
889
890 errno = 0;
891 tracee_pid = wait(&status);
892 if (tracee_pid <= 0) {
893 if (errno == EINTR)
894 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000895 kill_save_errno(pid, SIGKILL);
896 perror_msg_and_die("%s: unexpected wait result %d",
897 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200898 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200899 if (WIFEXITED(status)) {
900 if (WEXITSTATUS(status) == 0)
901 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000902 error_msg_and_die("%s: unexpected exit status %u",
903 __func__, WEXITSTATUS(status));
904 }
905 if (WIFSIGNALED(status)) {
906 error_msg_and_die("%s: unexpected signal %u",
907 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200908 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200909 if (!WIFSTOPPED(status)) {
910 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000911 error_msg_and_die("%s: unexpected wait status %x",
912 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200913 }
914 if (WSTOPSIG(status) == SIGSTOP) {
915 /*
916 * We don't check "options aren't accepted" error.
917 * If it happens, we'll never get (SIGTRAP | 0x80),
918 * and thus will decide to not use the option.
919 * IOW: the outcome of the test will be correct.
920 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000921 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
922 && errno != EINVAL && errno != EIO)
923 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200924 }
925 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
926 it_worked = 1;
927 }
928 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000929 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200930 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200931 }
932 }
933
934 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200935 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200936 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200937 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200938 fprintf(stderr, "ptrace_setoptions = %#x\n",
939 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200940 return;
941 }
942
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000943 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
944 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200945}
Wang Chaob13c0de2010-11-12 17:25:19 +0800946#endif
947
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000949main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000950{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 struct tcb *tcp;
952 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000953 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 struct sigaction sa;
955
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000956 progname = argv[0] ? argv[0] : "strace";
957
Denys Vlasenko75422762011-05-27 14:36:01 +0200958 strace_tracer_pid = getpid();
959
Roland McGrathee9d4352002-12-18 04:16:10 +0000960 /* Allocate the initial tcbtab. */
961 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200962 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200963 if (!tcbtab)
964 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200965 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200966 if (!tcp)
967 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200968 for (c = 0; c < tcbtabsize; c++)
969 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000970
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 outf = stderr;
972 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000973 set_sortby(DEFAULT_SORTBY);
974 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 qualify("trace=all");
976 qualify("abbrev=all");
977 qualify("verbose=all");
978 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000980 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000981#ifndef USE_PROCFS
982 "D"
983#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000984 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985 switch (c) {
986 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000987 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200988 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000989 }
990 cflag = CFLAG_ONLY_STATS;
991 break;
992 case 'C':
993 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200994 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000995 }
996 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997 break;
998 case 'd':
999 debug++;
1000 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001001#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001002 case 'D':
1003 daemonized_tracer = 1;
1004 break;
1005#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001006 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001007 optF = 1;
1008 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 case 'f':
1010 followfork++;
1011 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 case 'h':
1013 usage(stdout, 0);
1014 break;
1015 case 'i':
1016 iflag++;
1017 break;
1018 case 'q':
1019 qflag++;
1020 break;
1021 case 'r':
1022 rflag++;
1023 tflag++;
1024 break;
1025 case 't':
1026 tflag++;
1027 break;
1028 case 'T':
1029 dtime++;
1030 break;
1031 case 'x':
1032 xflag++;
1033 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001034 case 'y':
1035 show_fd_path = 1;
1036 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 case 'v':
1038 qualify("abbrev=none");
1039 break;
1040 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001041 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 exit(0);
1043 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001044 case 'z':
1045 not_failing_only = 1;
1046 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 case 'a':
1048 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001049 if (acolumn < 0)
1050 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 break;
1052 case 'e':
1053 qualify(optarg);
1054 break;
1055 case 'o':
1056 outfname = strdup(optarg);
1057 break;
1058 case 'O':
1059 set_overhead(atoi(optarg));
1060 break;
1061 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001062 pid = atoi(optarg);
1063 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001064 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 break;
1066 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001067 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001068 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 break;
1070 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001071 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001072 tcp->flags |= TCB_ATTACHED;
1073 pflag_seen++;
1074 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001075 case 'P':
1076 tracing_paths = 1;
1077 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001078 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001079 }
1080 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 case 's':
1082 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001083 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001084 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001085 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086 break;
1087 case 'S':
1088 set_sortby(optarg);
1089 break;
1090 case 'u':
1091 username = strdup(optarg);
1092 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001093 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001094 if (putenv(optarg) < 0)
1095 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001096 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097 default:
1098 usage(stderr, 1);
1099 break;
1100 }
1101 }
1102
Denys Vlasenko102ec492011-08-25 01:27:59 +02001103 acolumn_spaces = malloc(acolumn + 1);
1104 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001105 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001106 memset(acolumn_spaces, ' ', acolumn);
1107 acolumn_spaces[acolumn] = '\0';
1108
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001109 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001110 usage(stderr, 1);
1111
Wang Chaod322a4b2010-08-05 14:30:11 +08001112 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001113 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001114 }
1115
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001116 if (!followfork)
1117 followfork = optF;
1118
Roland McGrathcb9def62006-04-25 07:48:03 +00001119 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001120 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001121 }
1122
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 /* See if they want to run as another user. */
1124 if (username != NULL) {
1125 struct passwd *pent;
1126
1127 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001128 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001130 pent = getpwnam(username);
1131 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001132 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 }
1134 run_uid = pent->pw_uid;
1135 run_gid = pent->pw_gid;
1136 }
1137 else {
1138 run_uid = getuid();
1139 run_gid = getgid();
1140 }
1141
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001142#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001143 if (followfork)
1144 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001145 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001146#endif
1147
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 /* Check if they want to redirect the output. */
1149 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001150 /* See if they want to pipe the output. */
1151 if (outfname[0] == '|' || outfname[0] == '!') {
1152 /*
1153 * We can't do the <outfname>.PID funny business
1154 * when using popen, so prohibit it.
1155 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001156 if (followfork > 1)
1157 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1158 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001159 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001160 else if (followfork <= 1)
1161 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 }
1163
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001164 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1165 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001167 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001168 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001171 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001172
Roland McGrath54cc1c82007-11-03 23:34:11 +00001173 /* Valid states here:
1174 optind < argc pflag_seen outfname interactive
1175 1 0 0 1
1176 0 1 0 1
1177 1 0 1 0
1178 0 1 1 1
1179 */
1180
1181 /* STARTUP_CHILD must be called before the signal handlers get
1182 installed below as they are inherited into the spawned process.
1183 Also we do not need to be protected by them as during interruption
1184 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1185 if (!pflag_seen)
1186 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 sigemptyset(&empty_set);
1189 sigemptyset(&blocked_set);
1190 sa.sa_handler = SIG_IGN;
1191 sigemptyset(&sa.sa_mask);
1192 sa.sa_flags = 0;
1193 sigaction(SIGTTOU, &sa, NULL);
1194 sigaction(SIGTTIN, &sa, NULL);
1195 if (interactive) {
1196 sigaddset(&blocked_set, SIGHUP);
1197 sigaddset(&blocked_set, SIGINT);
1198 sigaddset(&blocked_set, SIGQUIT);
1199 sigaddset(&blocked_set, SIGPIPE);
1200 sigaddset(&blocked_set, SIGTERM);
1201 sa.sa_handler = interrupt;
1202#ifdef SUNOS4
1203 /* POSIX signals on sunos4.1 are a little broken. */
1204 sa.sa_flags = SA_INTERRUPT;
1205#endif /* SUNOS4 */
1206 }
1207 sigaction(SIGHUP, &sa, NULL);
1208 sigaction(SIGINT, &sa, NULL);
1209 sigaction(SIGQUIT, &sa, NULL);
1210 sigaction(SIGPIPE, &sa, NULL);
1211 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001212#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 sa.sa_handler = reaper;
1214 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001215#else
1216 /* Make sure SIGCHLD has the default action so that waitpid
1217 definitely works without losing track of children. The user
1218 should not have given us a bogus state to inherit, but he might
1219 have. Arguably we should detect SIG_IGN here and pass it on
1220 to children, but probably noone really needs that. */
1221 sa.sa_handler = SIG_DFL;
1222 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001223#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001225 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001226 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001227
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 if (trace() < 0)
1229 exit(1);
1230 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001231 fflush(NULL);
1232 if (exit_code > 0xff) {
1233 /* Child was killed by a signal, mimic that. */
1234 exit_code &= 0xff;
1235 signal(exit_code, SIG_DFL);
1236 raise(exit_code);
1237 /* Paranoia - what if this signal is not fatal?
1238 Exit with 128 + signo then. */
1239 exit_code += 128;
1240 }
1241 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242}
1243
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001244static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001245expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001246{
1247 /* Allocate some more TCBs and expand the table.
1248 We don't want to relocate the TCBs because our
1249 callers have pointers and it would be a pain.
1250 So tcbtab is a table of pointers. Since we never
1251 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001252 int i = tcbtabsize;
1253 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1254 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001255 if (!newtab || !newtcbs)
1256 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001257 tcbtabsize *= 2;
1258 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001259 while (i < tcbtabsize)
1260 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001261}
1262
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001264alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265{
1266 int i;
1267 struct tcb *tcp;
1268
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001269 if (nprocs == tcbtabsize)
1270 expand_tcbtab();
1271
Roland McGrathee9d4352002-12-18 04:16:10 +00001272 for (i = 0; i < tcbtabsize; i++) {
1273 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001275 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001277 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001278 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001279#if SUPPORTED_PERSONALITIES > 1
1280 tcp->currpers = current_personality;
1281#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001282#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001284#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001286 if (debug)
1287 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001288 if (command_options_parsed)
1289 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290 return tcp;
1291 }
1292 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001293 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294}
1295
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001296#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001297int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001298proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299{
1300 char proc[32];
1301 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001302#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001303 int i;
1304 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305 sigset_t signals;
1306 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001307#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001308#ifndef HAVE_POLLABLE_PROCFS
1309 static int last_pfd;
1310#endif
1311
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001312#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001313 /* Open the process pseudo-files in /proc. */
1314 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001315 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1316 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001317 perror("strace: open(\"/proc/...\", ...)");
1318 return -1;
1319 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001320 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001321 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001322 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1323 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001324 perror("strace: open(\"/proc/...\", ...)");
1325 return -1;
1326 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001327 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001328 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001329 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1330 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001331 perror("strace: open(\"/proc/...\", ...)");
1332 return -1;
1333 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001334 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001335#else
1336 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001337# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001338 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001339 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001340# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001341 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001342 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001343# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001344 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001345 perror("strace: open(\"/proc/...\", ...)");
1346 return -1;
1347 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001348 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001349#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001350#ifdef FREEBSD
1351 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001352 tcp->pfd_reg = open(proc, O_RDONLY);
1353 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001354 perror("strace: open(\"/proc/.../regs\", ...)");
1355 return -1;
1356 }
1357 if (cflag) {
1358 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001359 tcp->pfd_status = open(proc, O_RDONLY);
1360 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001361 perror("strace: open(\"/proc/.../status\", ...)");
1362 return -1;
1363 }
1364 } else
1365 tcp->pfd_status = -1;
1366#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001367 rebuild_pollv();
1368 if (!attaching) {
1369 /*
1370 * Wait for the child to pause. Because of a race
1371 * condition we have to poll for the event.
1372 */
1373 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001374 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001375 perror("strace: PIOCSTATUS");
1376 return -1;
1377 }
1378 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001379 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001380 }
1381 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001382#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001384 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001385 perror("strace: PIOCSTOP");
1386 return -1;
1387 }
Roland McGrath553a6092002-12-16 20:40:39 +00001388#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389#ifdef PIOCSET
1390 /* Set Run-on-Last-Close. */
1391 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001392 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001393 perror("PIOCSET PR_RLC");
1394 return -1;
1395 }
1396 /* Set or Reset Inherit-on-Fork. */
1397 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001398 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001399 perror("PIOC{SET,RESET} PR_FORK");
1400 return -1;
1401 }
1402#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001403#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1405 perror("PIOCSRLC");
1406 return -1;
1407 }
1408 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1409 perror("PIOC{S,R}FORK");
1410 return -1;
1411 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001412#else /* FREEBSD */
1413 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1414 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1415 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001416 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001417 }
1418 arg &= ~PF_LINGER;
1419 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001420 perror("PIOCSFL");
1421 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001422 }
1423#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001425#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001426 /* Enable all syscall entries we care about. */
1427 premptyset(&syscalls);
1428 for (i = 1; i < MAX_QUALS; ++i) {
1429 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001430 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001431 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001432 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001433 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001434 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001435#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001436 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001437#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001438#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001439 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001440#endif
1441#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001442 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001443#endif
1444#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001445 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001446#endif
1447 }
1448 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 perror("PIOCSENTRY");
1450 return -1;
1451 }
John Hughes19e49982001-10-19 08:59:12 +00001452 /* Enable the syscall exits. */
1453 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 perror("PIOSEXIT");
1455 return -1;
1456 }
John Hughes19e49982001-10-19 08:59:12 +00001457 /* Enable signals we care about. */
1458 premptyset(&signals);
1459 for (i = 1; i < MAX_QUALS; ++i) {
1460 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001461 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001462 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001463 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464 perror("PIOCSTRACE");
1465 return -1;
1466 }
John Hughes19e49982001-10-19 08:59:12 +00001467 /* Enable faults we care about */
1468 premptyset(&faults);
1469 for (i = 1; i < MAX_QUALS; ++i) {
1470 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001471 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001472 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001473 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474 perror("PIOCSFAULT");
1475 return -1;
1476 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001477#else /* FREEBSD */
1478 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001479 arg = S_SIG | S_SCE | S_SCX;
1480 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001481 perror("PIOCBIS");
1482 return -1;
1483 }
1484#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485 if (!attaching) {
1486#ifdef MIPS
1487 /*
1488 * The SGI PRSABORT doesn't work for pause() so
1489 * we send it a caught signal to wake it up.
1490 */
1491 kill(tcp->pid, SIGINT);
1492#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001493#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001495 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001496 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001497 perror("PIOCRUN");
1498 return -1;
1499 }
Roland McGrath553a6092002-12-16 20:40:39 +00001500#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001501#endif /* !MIPS*/
1502#ifdef FREEBSD
1503 /* wake up the child if it received the SIGSTOP */
1504 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001505#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001506 for (;;) {
1507 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001508 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 perror("PIOCWSTOP");
1510 return -1;
1511 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001512 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001513 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001514 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001515 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001516 break;
1517 }
1518 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001519#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001520 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001521 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1522#else
1523 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1524#endif
1525 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526 perror("PIOCRUN");
1527 return -1;
1528 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001529#ifdef FREEBSD
1530 /* handle the case where we "opened" the child before
1531 it did the kill -STOP */
1532 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1533 tcp->status.PR_WHAT == SIGSTOP)
1534 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001535#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 }
1537 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001538#ifdef FREEBSD
1539 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001540 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001541 /* We are attaching to an already running process.
1542 * Try to figure out the state of the process in syscalls,
1543 * to handle the first event well.
1544 * This is done by having a look at the "wchan" property of the
1545 * process, which tells where it is stopped (if it is). */
1546 FILE * status;
1547 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001548
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001549 sprintf(proc, "/proc/%d/status", tcp->pid);
1550 status = fopen(proc, "r");
1551 if (status &&
1552 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1553 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1554 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1555 strcmp(wchan, "stopevent")) {
1556 /* The process is asleep in the middle of a syscall.
1557 Fake the syscall entry event */
1558 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1559 tcp->status.PR_WHY = PR_SYSENTRY;
1560 trace_syscall(tcp);
1561 }
1562 if (status)
1563 fclose(status);
1564 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001565 }
1566#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567#ifndef HAVE_POLLABLE_PROCFS
1568 if (proc_poll_pipe[0] != -1)
1569 proc_poller(tcp->pfd);
1570 else if (nprocs > 1) {
1571 proc_poll_open();
1572 proc_poller(last_pfd);
1573 proc_poller(tcp->pfd);
1574 }
1575 last_pfd = tcp->pfd;
1576#endif /* !HAVE_POLLABLE_PROCFS */
1577 return 0;
1578}
1579
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001580#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001582struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001583pid2tcb(int pid)
1584{
1585 int i;
1586
1587 if (pid <= 0)
1588 return NULL;
1589
1590 for (i = 0; i < tcbtabsize; i++) {
1591 struct tcb *tcp = tcbtab[i];
1592 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1593 return tcp;
1594 }
1595
1596 return NULL;
1597}
1598
1599#ifdef USE_PROCFS
1600
1601static struct tcb *
1602first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603{
1604 int i;
1605 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001606 for (i = 0; i < tcbtabsize; i++) {
1607 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 if (tcp->flags & TCB_INUSE)
1609 return tcp;
1610 }
1611 return NULL;
1612}
1613
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001615pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616{
1617 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618
Roland McGrathca16be82003-01-10 19:55:28 +00001619 for (i = 0; i < tcbtabsize; i++) {
1620 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 if (tcp->pfd != pfd)
1622 continue;
1623 if (tcp->flags & TCB_INUSE)
1624 return tcp;
1625 }
1626 return NULL;
1627}
1628
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001629#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630
1631void
Denys Vlasenko12014262011-05-30 14:00:14 +02001632droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633{
1634 if (tcp->pid == 0)
1635 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001636
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001638 if (debug)
1639 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001640
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001641#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 if (tcp->pfd != -1) {
1643 close(tcp->pfd);
1644 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001645# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001646 if (tcp->pfd_reg != -1) {
1647 close(tcp->pfd_reg);
1648 tcp->pfd_reg = -1;
1649 }
1650 if (tcp->pfd_status != -1) {
1651 close(tcp->pfd_status);
1652 tcp->pfd_status = -1;
1653 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001654# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001655 tcp->flags = 0; /* rebuild_pollv needs it */
1656 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001658#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001659
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001660 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001662
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001663 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664}
1665
Roland McGrath0a463882007-07-05 18:43:16 +00001666/* detach traced process; continue with sig
1667 Never call DETACH twice on the same process as both unattached and
1668 attached-unstopped processes give the same ESRCH. For unattached process we
1669 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670
1671static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001672detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673{
1674 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001675#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001676 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001677#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678
1679 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001680 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681
1682#ifdef LINUX
1683 /*
1684 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001685 * before detaching. Arghh. We go through hoops
1686 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001688#if defined(SPARC)
1689#undef PTRACE_DETACH
1690#define PTRACE_DETACH PTRACE_SUNDETACH
1691#endif
Roland McGrath02203312007-06-11 22:06:31 +00001692 /*
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001693 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1694 * We must catch exactly one as otherwise the detached process
1695 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001696 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001697 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001698 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1699 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001701 }
1702 else if (errno != ESRCH) {
1703 /* Shouldn't happen. */
1704 perror("detach: ptrace(PTRACE_DETACH, ...)");
1705 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001706 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001707 if (errno != ESRCH)
1708 perror("detach: checking sanity");
1709 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001710 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001711 if (errno != ESRCH)
1712 perror("detach: stopping child");
1713 }
Roland McGrath02203312007-06-11 22:06:31 +00001714 else
1715 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001716 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001718#ifdef __WALL
1719 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1720 if (errno == ECHILD) /* Already gone. */
1721 break;
1722 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001723 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001724 break;
1725 }
1726#endif /* __WALL */
1727 /* No __WALL here. */
1728 if (waitpid(tcp->pid, &status, 0) < 0) {
1729 if (errno != ECHILD) {
1730 perror("detach: waiting");
1731 break;
1732 }
1733#ifdef __WCLONE
1734 /* If no processes, try clones. */
1735 if (wait4(tcp->pid, &status, __WCLONE,
1736 NULL) < 0) {
1737 if (errno != ECHILD)
1738 perror("detach: waiting");
1739 break;
1740 }
1741#endif /* __WCLONE */
1742 }
1743#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001744 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001745#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 if (!WIFSTOPPED(status)) {
1747 /* Au revoir, mon ami. */
1748 break;
1749 }
1750 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001751 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752 break;
1753 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001754 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001755 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001756 : WSTOPSIG(status));
1757 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001760 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001761#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762
1763#if defined(SUNOS4)
1764 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1765 if (sig && kill(tcp->pid, sig) < 0)
1766 perror("detach: kill");
1767 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001768 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769#endif /* SUNOS4 */
1770
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771 if (!qflag)
1772 fprintf(stderr, "Process %u detached\n", tcp->pid);
1773
1774 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001775
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 return error;
1777}
1778
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001779#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001781static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782{
1783 int pid;
1784 int status;
1785
1786 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 }
1788}
1789
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001790#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
1792static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001793cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794{
1795 int i;
1796 struct tcb *tcp;
1797
Roland McGrathee9d4352002-12-18 04:16:10 +00001798 for (i = 0; i < tcbtabsize; i++) {
1799 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800 if (!(tcp->flags & TCB_INUSE))
1801 continue;
1802 if (debug)
1803 fprintf(stderr,
1804 "cleanup: looking at pid %u\n", tcp->pid);
1805 if (tcp_last &&
1806 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001807 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001808 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 }
1810 if (tcp->flags & TCB_ATTACHED)
1811 detach(tcp, 0);
1812 else {
1813 kill(tcp->pid, SIGCONT);
1814 kill(tcp->pid, SIGTERM);
1815 }
1816 }
1817 if (cflag)
1818 call_summary(outf);
1819}
1820
1821static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001822interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823{
1824 interrupted = 1;
1825}
1826
1827#ifndef HAVE_STRERROR
1828
Roland McGrath6d2b3492002-12-30 00:51:30 +00001829#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830extern int sys_nerr;
1831extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001832#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833
1834const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001835strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836{
1837 static char buf[64];
1838
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001839 if (err_no < 1 || err_no >= sys_nerr) {
1840 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841 return buf;
1842 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001843 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844}
1845
1846#endif /* HAVE_STERRROR */
1847
1848#ifndef HAVE_STRSIGNAL
1849
Roland McGrath8f474e02003-01-14 07:53:33 +00001850#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001851extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001853#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1854extern char *_sys_siglist[];
1855#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856
1857const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001858strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859{
1860 static char buf[64];
1861
1862 if (sig < 1 || sig >= NSIG) {
1863 sprintf(buf, "Unknown signal %d", sig);
1864 return buf;
1865 }
1866#ifdef HAVE__SYS_SIGLIST
1867 return _sys_siglist[sig];
1868#else
1869 return sys_siglist[sig];
1870#endif
1871}
1872
1873#endif /* HAVE_STRSIGNAL */
1874
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001875#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876
1877static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001878rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879{
1880 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001881
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001882 free(pollv);
1883 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001884 if (!pollv)
1885 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001886
Roland McGrathca16be82003-01-10 19:55:28 +00001887 for (i = j = 0; i < tcbtabsize; i++) {
1888 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001889 if (!(tcp->flags & TCB_INUSE))
1890 continue;
1891 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001892 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893 j++;
1894 }
1895 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001896 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897 }
1898}
1899
1900#ifndef HAVE_POLLABLE_PROCFS
1901
1902static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001903proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 int i;
1906
1907 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001908 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909 }
1910 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001911 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912 }
1913}
1914
1915static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001916proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917{
1918 int i;
1919 int n;
1920 struct proc_pollfd pollinfo;
1921
Denys Vlasenko5d645812011-08-20 12:48:18 +02001922 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1923 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 return n;
1925 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001926 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927 }
1928 for (i = 0; i < nprocs; i++) {
1929 if (pollv[i].fd == pollinfo.fd)
1930 pollv[i].revents = pollinfo.revents;
1931 else
1932 pollv[i].revents = 0;
1933 }
1934 poller_pid = pollinfo.pid;
1935 return 1;
1936}
1937
1938static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001939wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940{
1941}
1942
1943static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001944proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945{
1946 struct proc_pollfd pollinfo;
1947 struct sigaction sa;
1948 sigset_t blocked_set, empty_set;
1949 int i;
1950 int n;
1951 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001952#ifdef FREEBSD
1953 struct procfs_status pfs;
1954#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955
1956 switch (fork()) {
1957 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001958 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959 case 0:
1960 break;
1961 default:
1962 return;
1963 }
1964
1965 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1966 sa.sa_flags = 0;
1967 sigemptyset(&sa.sa_mask);
1968 sigaction(SIGHUP, &sa, NULL);
1969 sigaction(SIGINT, &sa, NULL);
1970 sigaction(SIGQUIT, &sa, NULL);
1971 sigaction(SIGPIPE, &sa, NULL);
1972 sigaction(SIGTERM, &sa, NULL);
1973 sa.sa_handler = wakeup_handler;
1974 sigaction(SIGUSR1, &sa, NULL);
1975 sigemptyset(&blocked_set);
1976 sigaddset(&blocked_set, SIGUSR1);
1977 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1978 sigemptyset(&empty_set);
1979
1980 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001981 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001982 }
1983 n = rl.rlim_cur;
1984 for (i = 0; i < n; i++) {
1985 if (i != pfd && i != proc_poll_pipe[1])
1986 close(i);
1987 }
1988
1989 pollinfo.fd = pfd;
1990 pollinfo.pid = getpid();
1991 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001992#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001993 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1994#else
1995 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1996#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001997 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 switch (errno) {
1999 case EINTR:
2000 continue;
2001 case EBADF:
2002 pollinfo.revents = POLLERR;
2003 break;
2004 case ENOENT:
2005 pollinfo.revents = POLLHUP;
2006 break;
2007 default:
2008 perror("proc_poller: PIOCWSTOP");
2009 }
2010 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2011 _exit(0);
2012 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002013 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002014 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2015 sigsuspend(&empty_set);
2016 }
2017}
2018
2019#endif /* !HAVE_POLLABLE_PROCFS */
2020
2021static int
2022choose_pfd()
2023{
2024 int i, j;
2025 struct tcb *tcp;
2026
2027 static int last;
2028
2029 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002030 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 /*
2032 * The previous process is ready to run again. We'll
2033 * let it do so if it is currently in a syscall. This
2034 * heuristic improves the readability of the trace.
2035 */
2036 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002037 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038 return pollv[last].fd;
2039 }
2040
2041 for (i = 0; i < nprocs; i++) {
2042 /* Let competing children run round robin. */
2043 j = (i + last + 1) % nprocs;
2044 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2045 tcp = pfd2tcb(pollv[j].fd);
2046 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002047 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 }
2049 droptcb(tcp);
2050 return -1;
2051 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002052 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 last = j;
2054 return pollv[j].fd;
2055 }
2056 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002057 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058}
2059
2060static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002061trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002063#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002064 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002065#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002066 struct tcb *tcp;
2067 int pfd;
2068 int what;
2069 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002070 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002071
2072 for (;;) {
2073 if (interactive)
2074 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2075
2076 if (nprocs == 0)
2077 break;
2078
2079 switch (nprocs) {
2080 case 1:
2081#ifndef HAVE_POLLABLE_PROCFS
2082 if (proc_poll_pipe[0] == -1) {
2083#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002084 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002085 if (!tcp)
2086 continue;
2087 pfd = tcp->pfd;
2088 if (pfd == -1)
2089 continue;
2090 break;
2091#ifndef HAVE_POLLABLE_PROCFS
2092 }
2093 /* fall through ... */
2094#endif /* !HAVE_POLLABLE_PROCFS */
2095 default:
2096#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002097#ifdef POLL_HACK
2098 /* On some systems (e.g. UnixWare) we get too much ugly
2099 "unfinished..." stuff when multiple proceses are in
2100 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002101
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002102 if (in_syscall) {
2103 struct pollfd pv;
2104 tcp = in_syscall;
2105 in_syscall = NULL;
2106 pv.fd = tcp->pfd;
2107 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002108 what = poll(&pv, 1, 1);
2109 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002110 if (interrupted)
2111 return 0;
2112 continue;
2113 }
2114 else if (what == 1 && pv.revents & POLLWANT) {
2115 goto FOUND;
2116 }
2117 }
2118#endif
2119
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002120 if (poll(pollv, nprocs, INFTIM) < 0) {
2121 if (interrupted)
2122 return 0;
2123 continue;
2124 }
2125#else /* !HAVE_POLLABLE_PROCFS */
2126 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2127 if (interrupted)
2128 return 0;
2129 continue;
2130 }
2131#endif /* !HAVE_POLLABLE_PROCFS */
2132 pfd = choose_pfd();
2133 if (pfd == -1)
2134 continue;
2135 break;
2136 }
2137
2138 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002139 tcp = pfd2tcb(pfd);
2140 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002141 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 }
John Hughesb6643082002-05-23 11:02:22 +00002143#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002144 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002145#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 /* Get the status of the process. */
2147 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002148#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002149 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002150#else /* FREEBSD */
2151 /* Thanks to some scheduling mystery, the first poller
2152 sometimes waits for the already processed end of fork
2153 event. Doing a non blocking poll here solves the problem. */
2154 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002155 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002156 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002157 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002158#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002159 ioctl_errno = errno;
2160#ifndef HAVE_POLLABLE_PROCFS
2161 if (proc_poll_pipe[0] != -1) {
2162 if (ioctl_result < 0)
2163 kill(poller_pid, SIGKILL);
2164 else
2165 kill(poller_pid, SIGUSR1);
2166 }
2167#endif /* !HAVE_POLLABLE_PROCFS */
2168 }
2169 if (interrupted)
2170 return 0;
2171
2172 if (interactive)
2173 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2174
2175 if (ioctl_result < 0) {
2176 /* Find out what happened if it failed. */
2177 switch (ioctl_errno) {
2178 case EINTR:
2179 case EBADF:
2180 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002181#ifdef FREEBSD
2182 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002183#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 case ENOENT:
2185 droptcb(tcp);
2186 continue;
2187 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002188 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 }
2190 }
2191
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002192#ifdef FREEBSD
2193 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2194 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002195 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002196 continue;
2197 }
Roland McGrath553a6092002-12-16 20:40:39 +00002198#endif
2199
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 /* clear the just started flag */
2201 tcp->flags &= ~TCB_STARTUP;
2202
2203 /* set current output file */
2204 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002205 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002206
2207 if (cflag) {
2208 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002209#ifdef FREEBSD
2210 char buf[1024];
2211 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212
Denys Vlasenko5d645812011-08-20 12:48:18 +02002213 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2214 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002215 buf[len] = '\0';
2216 sscanf(buf,
2217 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2218 &stime.tv_sec, &stime.tv_usec);
2219 } else
2220 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002221#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002222 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2223 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002224#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2226 tcp->stime = stime;
2227 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002228 what = tcp->status.PR_WHAT;
2229 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002230#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002232 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2233 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002235 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 }
2237 }
2238 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002239#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002240 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002241#ifdef POLL_HACK
2242 in_syscall = tcp;
2243#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244 case PR_SYSEXIT:
2245 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002246 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002247 }
2248 break;
2249 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002250 if (cflag != CFLAG_ONLY_STATS
2251 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002252 printleader(tcp);
2253 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002254 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002255 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002256#ifdef PR_INFO
2257 if (tcp->status.PR_INFO.si_signo == what) {
2258 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002259 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002260 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002261 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002262 }
2263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264 }
2265 break;
2266 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002267 if (cflag != CFLAGS_ONLY_STATS
2268 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002269 printleader(tcp);
2270 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002271 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002272 }
2273 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002274#ifdef FREEBSD
2275 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002276 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002277#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002278 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002279 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002280 break;
2281 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002282 /* Remember current print column before continuing. */
2283 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002284 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002285#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002286 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002287#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002288 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002289#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002290 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002291 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002292 }
2293 }
2294 return 0;
2295}
2296
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002297#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298
Roland McGratheb9e2e82009-06-02 16:49:22 -07002299static int
2300trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002301{
2302 int pid;
2303 int wait_errno;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002304 int status, sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 struct tcb *tcp;
2306#ifdef LINUX
2307 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002308 struct rusage *rup = cflag ? &ru : NULL;
2309# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002310 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002311# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312#endif /* LINUX */
2313
Roland McGratheb9e2e82009-06-02 16:49:22 -07002314 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002315 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002316 return 0;
2317 if (interactive)
2318 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002319#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002320# ifdef __WALL
2321 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002322 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002323 /* this kernel does not support __WALL */
2324 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002325 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002326 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002327 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002328 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002329 pid = wait4(-1, &status, __WCLONE, rup);
2330 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002331 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002332 }
2333 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002334# else
2335 pid = wait4(-1, &status, 0, rup);
2336# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337#endif /* LINUX */
2338#ifdef SUNOS4
2339 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002340#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002342 if (interactive)
2343 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002344
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002345 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002346 switch (wait_errno) {
2347 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002349 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002350 /*
2351 * We would like to verify this case
2352 * but sometimes a race in Solbourne's
2353 * version of SunOS sometimes reports
2354 * ECHILD before sending us SIGCHILD.
2355 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002356 return 0;
2357 default:
2358 errno = wait_errno;
2359 perror("strace: wait");
2360 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002361 }
2362 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002363 if (pid == popen_pid) {
2364 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002365 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002366 continue;
2367 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002368 if (debug) {
2369 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2370#ifdef LINUX
2371 unsigned ev = (unsigned)status >> 16;
2372 if (ev) {
2373 static const char *const event_names[] = {
2374 [PTRACE_EVENT_CLONE] = "CLONE",
2375 [PTRACE_EVENT_FORK] = "FORK",
2376 [PTRACE_EVENT_VFORK] = "VFORK",
2377 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2378 [PTRACE_EVENT_EXEC] = "EXEC",
2379 [PTRACE_EVENT_EXIT] = "EXIT",
2380 };
2381 const char *e;
2382 if (ev < ARRAY_SIZE(event_names))
2383 e = event_names[ev];
2384 else {
2385 sprintf(buf, "?? (%u)", ev);
2386 e = buf;
2387 }
2388 fprintf(stderr, " PTRACE_EVENT_%s", e);
2389 }
2390#endif
2391 strcpy(buf, "???");
2392 if (WIFSIGNALED(status))
2393#ifdef WCOREDUMP
2394 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2395 WCOREDUMP(status) ? "core," : "",
2396 signame(WTERMSIG(status)));
2397#else
2398 sprintf(buf, "WIFSIGNALED,sig=%s",
2399 signame(WTERMSIG(status)));
2400#endif
2401 if (WIFEXITED(status))
2402 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2403 if (WIFSTOPPED(status))
2404 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002405#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002406 if (WIFCONTINUED(status))
2407 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002408#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002409 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2410 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411
2412 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002413 tcp = pid2tcb(pid);
2414 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002415#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002416 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002417 /* This is needed to go with the CLONE_PTRACE
2418 changes in process.c/util.c: we might see
2419 the child's initial trap before we see the
2420 parent return from the clone syscall.
2421 Leave the child suspended until the parent
2422 returns from its system call. Only then
2423 will we have the association of parent and
2424 child so that we know how to do clearbpt
2425 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002426 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002427 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002428 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002429 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002430 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002431 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002432 else
2433 /* This can happen if a clone call used
2434 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002435#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002436 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002437 if (WIFSTOPPED(status))
2438 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002439 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002440 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002441 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002442 /* set current output file */
2443 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002444 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002445#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002446 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2448 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002450#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002451
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002452 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002453 if (pid == strace_child)
2454 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002455 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2457 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002458#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002459 tprintf("+++ killed by %s %s+++",
2460 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002461 WCOREDUMP(status) ? "(core dumped) " : "");
2462#else
2463 tprintf("+++ killed by %s +++",
2464 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002465#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002466 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002467 }
2468 droptcb(tcp);
2469 continue;
2470 }
2471 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002472 if (pid == strace_child)
2473 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002474 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002475 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002476 tprintf(" <unfinished ... exit status %d>\n",
2477 WEXITSTATUS(status));
2478 tcp_last = NULL;
2479 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002480 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2481 printleader(tcp);
2482 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2483 printtrailer();
2484 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002485 droptcb(tcp);
2486 continue;
2487 }
2488 if (!WIFSTOPPED(status)) {
2489 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2490 droptcb(tcp);
2491 continue;
2492 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002494 /* Is this the very first time we see this tracee stopped? */
2495 if (tcp->flags & TCB_STARTUP) {
2496 if (debug)
2497 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002498 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002500 /*
2501 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002502 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002503 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002504 if (clearbpt(tcp) < 0) {
2505 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002506 droptcb(tcp);
2507 cleanup();
2508 return -1;
2509 }
2510 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002511#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002512 if (ptrace_setoptions) {
2513 if (debug)
2514 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2515 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2516 if (errno != ESRCH) {
2517 /* Should never happen, really */
2518 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002519 }
2520 }
2521 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002522#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002523 }
2524
2525 if (((unsigned)status >> 16) != 0) {
2526 /* Ptrace event (we ignore all of them for now) */
2527 goto restart_tracee_with_sig_0;
2528 }
2529
2530 sig = WSTOPSIG(status);
2531
2532 /* Is this post-attach SIGSTOP?
2533 * Interestingly, the process may stop
2534 * with STOPSIG equal to some other signal
2535 * than SIGSTOP if we happend to attach
2536 * just before the process takes a signal.
2537 */
2538 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2539 if (debug)
2540 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2541 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002542 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 }
2544
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002545 if (sig != syscall_trap_sig) {
2546 if (sig == SIGSTOP &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002547 (tcp->flags & TCB_SIGTRAPPED)) {
2548 /*
2549 * Trapped attempt to block SIGTRAP
2550 * Hope we are back in control now.
2551 */
2552 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002553 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002554 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002555 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002556 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002557 siginfo_t si;
2558#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002559 long pc = 0;
2560 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002561
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002562 upeek(tcp, PT_CR_IPSR, &psr);
2563 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002564
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002565# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002566 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002567# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002568# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002569#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002570# define PC_FORMAT_STR ""
2571# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002572#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002573 printleader(tcp);
Dmitry V. Levin436d8922011-11-29 00:15:59 +00002574 if (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002575 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002576 printsiginfo(&si, verbose(tcp));
2577 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002578 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002579 PC_FORMAT_ARG);
2580 } else
2581 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002582 strsignal(sig),
2583 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002584 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002585 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002586 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002587 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002588 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002589
2590 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002591 if (interrupted)
2592 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002593
2594 /* This should be syscall entry or exit.
2595 * (Or it still can be that pesky post-execve SIGTRAP!)
2596 * Handle it.
2597 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002598 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2599 /* ptrace() failed in trace_syscall() with ESRCH.
2600 * Likely a result of process disappearing mid-flight.
2601 * Observed case: exit_group() terminating
2602 * all processes in thread group. In this case, threads
2603 * "disappear" in an unpredictable moment without any
2604 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002605 */
2606 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002607 if (tcp_last) {
2608 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002609 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002610 */
2611 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002612 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002613 printtrailer();
2614 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002616 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002617 ptrace(PTRACE_KILL,
2618 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619 droptcb(tcp);
2620 }
2621 continue;
2622 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002623 restart_tracee_with_sig_0:
2624 sig = 0;
2625 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002626 /* Remember current print column before continuing. */
2627 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002628 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629 cleanup();
2630 return -1;
2631 }
2632 }
2633 return 0;
2634}
2635
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002636#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002638void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002639tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002640{
2641 va_list args;
2642
Andreas Schwabe5355de2009-10-27 16:56:43 +01002643 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002644 if (outf) {
2645 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002646 if (n < 0) {
2647 if (outf != stderr)
2648 perror(outfname == NULL
2649 ? "<writing to pipe>" : outfname);
2650 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002651 curcol += n;
2652 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002653 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002654}
2655
2656void
2657tprints(const char *str)
2658{
2659 if (outf) {
2660 int n = fputs(str, outf);
2661 if (n >= 0) {
2662 curcol += strlen(str);
2663 return;
2664 }
2665 if (outf != stderr)
2666 perror(outfname == NULL
2667 ? "<writing to pipe>" : outfname);
2668 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002669}
2670
2671void
Denys Vlasenko12014262011-05-30 14:00:14 +02002672printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002673{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002674 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002675 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002676 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002677 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002678 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002679 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002680 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002681 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002682 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002683 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002684 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002685 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002686 }
2687 curcol = 0;
2688 if ((followfork == 1 || pflag_seen > 1) && outfname)
2689 tprintf("%-5d ", tcp->pid);
2690 else if (nprocs > 1 && !outfname)
2691 tprintf("[pid %5u] ", tcp->pid);
2692 if (tflag) {
2693 char str[sizeof("HH:MM:SS")];
2694 struct timeval tv, dtv;
2695 static struct timeval otv;
2696
2697 gettimeofday(&tv, NULL);
2698 if (rflag) {
2699 if (otv.tv_sec == 0)
2700 otv = tv;
2701 tv_sub(&dtv, &tv, &otv);
2702 tprintf("%6ld.%06ld ",
2703 (long) dtv.tv_sec, (long) dtv.tv_usec);
2704 otv = tv;
2705 }
2706 else if (tflag > 2) {
2707 tprintf("%ld.%06ld ",
2708 (long) tv.tv_sec, (long) tv.tv_usec);
2709 }
2710 else {
2711 time_t local = tv.tv_sec;
2712 strftime(str, sizeof(str), "%T", localtime(&local));
2713 if (tflag > 1)
2714 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2715 else
2716 tprintf("%s ", str);
2717 }
2718 }
2719 if (iflag)
2720 printcall(tcp);
2721}
2722
2723void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002724tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002725{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002726 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002727 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002728}
2729
2730void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002731printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002732{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002733 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002734 tcp_last = NULL;
2735}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002736
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002737#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002738
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002739int
2740mp_ioctl(int fd, int cmd, void *arg, int size)
2741{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002742 struct iovec iov[2];
2743 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002744
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002745 iov[0].iov_base = &cmd;
2746 iov[0].iov_len = sizeof cmd;
2747 if (arg) {
2748 ++n;
2749 iov[1].iov_base = arg;
2750 iov[1].iov_len = size;
2751 }
Roland McGrath553a6092002-12-16 20:40:39 +00002752
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002753 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002754}
2755
2756#endif