blob: 84c59b7b573cf572d035ecc339c916836bf9bdf5 [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 */
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001279#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001281#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001282 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001283 if (debug)
1284 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001285 if (command_options_parsed)
1286 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287 return tcp;
1288 }
1289 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001290 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291}
1292
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001293#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001295proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296{
1297 char proc[32];
1298 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001299#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001300 int i;
1301 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 sigset_t signals;
1303 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001304#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305#ifndef HAVE_POLLABLE_PROCFS
1306 static int last_pfd;
1307#endif
1308
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001309#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001310 /* Open the process pseudo-files in /proc. */
1311 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001312 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1313 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 perror("strace: open(\"/proc/...\", ...)");
1315 return -1;
1316 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001317 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001318 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001319 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1320 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001321 perror("strace: open(\"/proc/...\", ...)");
1322 return -1;
1323 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001324 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001325 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001326 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1327 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001328 perror("strace: open(\"/proc/...\", ...)");
1329 return -1;
1330 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001331 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001332#else
1333 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001334# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001335 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001336 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001337# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001339 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001340# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001341 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001342 perror("strace: open(\"/proc/...\", ...)");
1343 return -1;
1344 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001345 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001346#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001347#ifdef FREEBSD
1348 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001349 tcp->pfd_reg = open(proc, O_RDONLY);
1350 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001351 perror("strace: open(\"/proc/.../regs\", ...)");
1352 return -1;
1353 }
1354 if (cflag) {
1355 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001356 tcp->pfd_status = open(proc, O_RDONLY);
1357 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001358 perror("strace: open(\"/proc/.../status\", ...)");
1359 return -1;
1360 }
1361 } else
1362 tcp->pfd_status = -1;
1363#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001364 rebuild_pollv();
1365 if (!attaching) {
1366 /*
1367 * Wait for the child to pause. Because of a race
1368 * condition we have to poll for the event.
1369 */
1370 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001371 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001372 perror("strace: PIOCSTATUS");
1373 return -1;
1374 }
1375 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001376 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001377 }
1378 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001379#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001380 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001381 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001382 perror("strace: PIOCSTOP");
1383 return -1;
1384 }
Roland McGrath553a6092002-12-16 20:40:39 +00001385#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386#ifdef PIOCSET
1387 /* Set Run-on-Last-Close. */
1388 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001389 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390 perror("PIOCSET PR_RLC");
1391 return -1;
1392 }
1393 /* Set or Reset Inherit-on-Fork. */
1394 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001395 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 perror("PIOC{SET,RESET} PR_FORK");
1397 return -1;
1398 }
1399#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001400#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1402 perror("PIOCSRLC");
1403 return -1;
1404 }
1405 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1406 perror("PIOC{S,R}FORK");
1407 return -1;
1408 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001409#else /* FREEBSD */
1410 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1411 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1412 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001413 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001414 }
1415 arg &= ~PF_LINGER;
1416 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001417 perror("PIOCSFL");
1418 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001419 }
1420#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001422#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001423 /* Enable all syscall entries we care about. */
1424 premptyset(&syscalls);
1425 for (i = 1; i < MAX_QUALS; ++i) {
1426 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001427 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001428 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001429 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001430 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001431 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001432#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001433 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001434#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001435#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001436 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001437#endif
1438#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001439 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001440#endif
1441#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001442 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001443#endif
1444 }
1445 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446 perror("PIOCSENTRY");
1447 return -1;
1448 }
John Hughes19e49982001-10-19 08:59:12 +00001449 /* Enable the syscall exits. */
1450 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 perror("PIOSEXIT");
1452 return -1;
1453 }
John Hughes19e49982001-10-19 08:59:12 +00001454 /* Enable signals we care about. */
1455 premptyset(&signals);
1456 for (i = 1; i < MAX_QUALS; ++i) {
1457 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001458 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001459 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001460 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 perror("PIOCSTRACE");
1462 return -1;
1463 }
John Hughes19e49982001-10-19 08:59:12 +00001464 /* Enable faults we care about */
1465 premptyset(&faults);
1466 for (i = 1; i < MAX_QUALS; ++i) {
1467 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001468 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001469 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001470 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 perror("PIOCSFAULT");
1472 return -1;
1473 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001474#else /* FREEBSD */
1475 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001476 arg = S_SIG | S_SCE | S_SCX;
1477 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001478 perror("PIOCBIS");
1479 return -1;
1480 }
1481#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 if (!attaching) {
1483#ifdef MIPS
1484 /*
1485 * The SGI PRSABORT doesn't work for pause() so
1486 * we send it a caught signal to wake it up.
1487 */
1488 kill(tcp->pid, SIGINT);
1489#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001490#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001492 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001493 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 perror("PIOCRUN");
1495 return -1;
1496 }
Roland McGrath553a6092002-12-16 20:40:39 +00001497#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001498#endif /* !MIPS*/
1499#ifdef FREEBSD
1500 /* wake up the child if it received the SIGSTOP */
1501 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001502#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 for (;;) {
1504 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001505 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001506 perror("PIOCWSTOP");
1507 return -1;
1508 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001509 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001510 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001511 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001512 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 break;
1514 }
1515 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001516#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001517 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001518 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1519#else
1520 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1521#endif
1522 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 perror("PIOCRUN");
1524 return -1;
1525 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001526#ifdef FREEBSD
1527 /* handle the case where we "opened" the child before
1528 it did the kill -STOP */
1529 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1530 tcp->status.PR_WHAT == SIGSTOP)
1531 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001532#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 }
1534 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001535#ifdef FREEBSD
1536 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001537 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001538 /* We are attaching to an already running process.
1539 * Try to figure out the state of the process in syscalls,
1540 * to handle the first event well.
1541 * This is done by having a look at the "wchan" property of the
1542 * process, which tells where it is stopped (if it is). */
1543 FILE * status;
1544 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001545
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001546 sprintf(proc, "/proc/%d/status", tcp->pid);
1547 status = fopen(proc, "r");
1548 if (status &&
1549 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1550 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1551 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1552 strcmp(wchan, "stopevent")) {
1553 /* The process is asleep in the middle of a syscall.
1554 Fake the syscall entry event */
1555 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1556 tcp->status.PR_WHY = PR_SYSENTRY;
1557 trace_syscall(tcp);
1558 }
1559 if (status)
1560 fclose(status);
1561 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001562 }
1563#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564#ifndef HAVE_POLLABLE_PROCFS
1565 if (proc_poll_pipe[0] != -1)
1566 proc_poller(tcp->pfd);
1567 else if (nprocs > 1) {
1568 proc_poll_open();
1569 proc_poller(last_pfd);
1570 proc_poller(tcp->pfd);
1571 }
1572 last_pfd = tcp->pfd;
1573#endif /* !HAVE_POLLABLE_PROCFS */
1574 return 0;
1575}
1576
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001577#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001579struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001580pid2tcb(int pid)
1581{
1582 int i;
1583
1584 if (pid <= 0)
1585 return NULL;
1586
1587 for (i = 0; i < tcbtabsize; i++) {
1588 struct tcb *tcp = tcbtab[i];
1589 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1590 return tcp;
1591 }
1592
1593 return NULL;
1594}
1595
1596#ifdef USE_PROCFS
1597
1598static struct tcb *
1599first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600{
1601 int i;
1602 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001603 for (i = 0; i < tcbtabsize; i++) {
1604 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605 if (tcp->flags & TCB_INUSE)
1606 return tcp;
1607 }
1608 return NULL;
1609}
1610
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001611static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001612pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613{
1614 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615
Roland McGrathca16be82003-01-10 19:55:28 +00001616 for (i = 0; i < tcbtabsize; i++) {
1617 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618 if (tcp->pfd != pfd)
1619 continue;
1620 if (tcp->flags & TCB_INUSE)
1621 return tcp;
1622 }
1623 return NULL;
1624}
1625
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001626#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627
1628void
Denys Vlasenko12014262011-05-30 14:00:14 +02001629droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630{
1631 if (tcp->pid == 0)
1632 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001633
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001635 if (debug)
1636 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001637
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001638#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 if (tcp->pfd != -1) {
1640 close(tcp->pfd);
1641 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001642# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001643 if (tcp->pfd_reg != -1) {
1644 close(tcp->pfd_reg);
1645 tcp->pfd_reg = -1;
1646 }
1647 if (tcp->pfd_status != -1) {
1648 close(tcp->pfd_status);
1649 tcp->pfd_status = -1;
1650 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001651# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001652 tcp->flags = 0; /* rebuild_pollv needs it */
1653 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001655#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001656
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001657 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001659
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001660 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661}
1662
Roland McGrath0a463882007-07-05 18:43:16 +00001663/* detach traced process; continue with sig
1664 Never call DETACH twice on the same process as both unattached and
1665 attached-unstopped processes give the same ESRCH. For unattached process we
1666 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667
1668static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001669detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670{
1671 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001672#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001673 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001674#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675
1676 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001677 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678
1679#ifdef LINUX
1680 /*
1681 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001682 * before detaching. Arghh. We go through hoops
1683 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001685#if defined(SPARC)
1686#undef PTRACE_DETACH
1687#define PTRACE_DETACH PTRACE_SUNDETACH
1688#endif
Roland McGrath02203312007-06-11 22:06:31 +00001689 /*
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001690 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1691 * We must catch exactly one as otherwise the detached process
1692 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001693 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001694 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001695 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1696 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001698 }
1699 else if (errno != ESRCH) {
1700 /* Shouldn't happen. */
1701 perror("detach: ptrace(PTRACE_DETACH, ...)");
1702 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001703 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001704 if (errno != ESRCH)
1705 perror("detach: checking sanity");
1706 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001707 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001708 if (errno != ESRCH)
1709 perror("detach: stopping child");
1710 }
Roland McGrath02203312007-06-11 22:06:31 +00001711 else
1712 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001713 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001715#ifdef __WALL
1716 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1717 if (errno == ECHILD) /* Already gone. */
1718 break;
1719 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001720 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001721 break;
1722 }
1723#endif /* __WALL */
1724 /* No __WALL here. */
1725 if (waitpid(tcp->pid, &status, 0) < 0) {
1726 if (errno != ECHILD) {
1727 perror("detach: waiting");
1728 break;
1729 }
1730#ifdef __WCLONE
1731 /* If no processes, try clones. */
1732 if (wait4(tcp->pid, &status, __WCLONE,
1733 NULL) < 0) {
1734 if (errno != ECHILD)
1735 perror("detach: waiting");
1736 break;
1737 }
1738#endif /* __WCLONE */
1739 }
1740#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001741 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001742#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743 if (!WIFSTOPPED(status)) {
1744 /* Au revoir, mon ami. */
1745 break;
1746 }
1747 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001748 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749 break;
1750 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001751 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001752 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001753 : WSTOPSIG(status));
1754 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001757 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001758#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759
1760#if defined(SUNOS4)
1761 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1762 if (sig && kill(tcp->pid, sig) < 0)
1763 perror("detach: kill");
1764 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001765 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766#endif /* SUNOS4 */
1767
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768 if (!qflag)
1769 fprintf(stderr, "Process %u detached\n", tcp->pid);
1770
1771 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001772
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773 return error;
1774}
1775
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001776#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001778static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779{
1780 int pid;
1781 int status;
1782
1783 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784 }
1785}
1786
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001787#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788
1789static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001790cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791{
1792 int i;
1793 struct tcb *tcp;
1794
Roland McGrathee9d4352002-12-18 04:16:10 +00001795 for (i = 0; i < tcbtabsize; i++) {
1796 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 if (!(tcp->flags & TCB_INUSE))
1798 continue;
1799 if (debug)
1800 fprintf(stderr,
1801 "cleanup: looking at pid %u\n", tcp->pid);
1802 if (tcp_last &&
1803 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001804 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001805 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806 }
1807 if (tcp->flags & TCB_ATTACHED)
1808 detach(tcp, 0);
1809 else {
1810 kill(tcp->pid, SIGCONT);
1811 kill(tcp->pid, SIGTERM);
1812 }
1813 }
1814 if (cflag)
1815 call_summary(outf);
1816}
1817
1818static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001819interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820{
1821 interrupted = 1;
1822}
1823
1824#ifndef HAVE_STRERROR
1825
Roland McGrath6d2b3492002-12-30 00:51:30 +00001826#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001827extern int sys_nerr;
1828extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001829#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830
1831const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001832strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833{
1834 static char buf[64];
1835
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001836 if (err_no < 1 || err_no >= sys_nerr) {
1837 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838 return buf;
1839 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001840 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841}
1842
1843#endif /* HAVE_STERRROR */
1844
1845#ifndef HAVE_STRSIGNAL
1846
Roland McGrath8f474e02003-01-14 07:53:33 +00001847#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001848extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001850#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1851extern char *_sys_siglist[];
1852#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853
1854const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001855strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001856{
1857 static char buf[64];
1858
1859 if (sig < 1 || sig >= NSIG) {
1860 sprintf(buf, "Unknown signal %d", sig);
1861 return buf;
1862 }
1863#ifdef HAVE__SYS_SIGLIST
1864 return _sys_siglist[sig];
1865#else
1866 return sys_siglist[sig];
1867#endif
1868}
1869
1870#endif /* HAVE_STRSIGNAL */
1871
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001872#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873
1874static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001875rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876{
1877 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001879 free(pollv);
1880 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001881 if (!pollv)
1882 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001883
Roland McGrathca16be82003-01-10 19:55:28 +00001884 for (i = j = 0; i < tcbtabsize; i++) {
1885 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 if (!(tcp->flags & TCB_INUSE))
1887 continue;
1888 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001889 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890 j++;
1891 }
1892 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001893 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001894 }
1895}
1896
1897#ifndef HAVE_POLLABLE_PROCFS
1898
1899static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001900proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 int i;
1903
1904 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001905 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001906 }
1907 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001908 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001909 }
1910}
1911
1912static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001913proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914{
1915 int i;
1916 int n;
1917 struct proc_pollfd pollinfo;
1918
Denys Vlasenko5d645812011-08-20 12:48:18 +02001919 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1920 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 return n;
1922 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001923 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 }
1925 for (i = 0; i < nprocs; i++) {
1926 if (pollv[i].fd == pollinfo.fd)
1927 pollv[i].revents = pollinfo.revents;
1928 else
1929 pollv[i].revents = 0;
1930 }
1931 poller_pid = pollinfo.pid;
1932 return 1;
1933}
1934
1935static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001936wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937{
1938}
1939
1940static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001941proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942{
1943 struct proc_pollfd pollinfo;
1944 struct sigaction sa;
1945 sigset_t blocked_set, empty_set;
1946 int i;
1947 int n;
1948 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001949#ifdef FREEBSD
1950 struct procfs_status pfs;
1951#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952
1953 switch (fork()) {
1954 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001955 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001956 case 0:
1957 break;
1958 default:
1959 return;
1960 }
1961
1962 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1963 sa.sa_flags = 0;
1964 sigemptyset(&sa.sa_mask);
1965 sigaction(SIGHUP, &sa, NULL);
1966 sigaction(SIGINT, &sa, NULL);
1967 sigaction(SIGQUIT, &sa, NULL);
1968 sigaction(SIGPIPE, &sa, NULL);
1969 sigaction(SIGTERM, &sa, NULL);
1970 sa.sa_handler = wakeup_handler;
1971 sigaction(SIGUSR1, &sa, NULL);
1972 sigemptyset(&blocked_set);
1973 sigaddset(&blocked_set, SIGUSR1);
1974 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1975 sigemptyset(&empty_set);
1976
1977 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001978 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001979 }
1980 n = rl.rlim_cur;
1981 for (i = 0; i < n; i++) {
1982 if (i != pfd && i != proc_poll_pipe[1])
1983 close(i);
1984 }
1985
1986 pollinfo.fd = pfd;
1987 pollinfo.pid = getpid();
1988 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001989#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001990 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1991#else
1992 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1993#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001994 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995 switch (errno) {
1996 case EINTR:
1997 continue;
1998 case EBADF:
1999 pollinfo.revents = POLLERR;
2000 break;
2001 case ENOENT:
2002 pollinfo.revents = POLLHUP;
2003 break;
2004 default:
2005 perror("proc_poller: PIOCWSTOP");
2006 }
2007 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2008 _exit(0);
2009 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002010 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2012 sigsuspend(&empty_set);
2013 }
2014}
2015
2016#endif /* !HAVE_POLLABLE_PROCFS */
2017
2018static int
2019choose_pfd()
2020{
2021 int i, j;
2022 struct tcb *tcp;
2023
2024 static int last;
2025
2026 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002027 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 /*
2029 * The previous process is ready to run again. We'll
2030 * let it do so if it is currently in a syscall. This
2031 * heuristic improves the readability of the trace.
2032 */
2033 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002034 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 return pollv[last].fd;
2036 }
2037
2038 for (i = 0; i < nprocs; i++) {
2039 /* Let competing children run round robin. */
2040 j = (i + last + 1) % nprocs;
2041 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2042 tcp = pfd2tcb(pollv[j].fd);
2043 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002044 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045 }
2046 droptcb(tcp);
2047 return -1;
2048 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002049 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050 last = j;
2051 return pollv[j].fd;
2052 }
2053 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002054 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055}
2056
2057static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002058trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002059{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002060#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002061 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002062#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063 struct tcb *tcp;
2064 int pfd;
2065 int what;
2066 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002067 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068
2069 for (;;) {
2070 if (interactive)
2071 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2072
2073 if (nprocs == 0)
2074 break;
2075
2076 switch (nprocs) {
2077 case 1:
2078#ifndef HAVE_POLLABLE_PROCFS
2079 if (proc_poll_pipe[0] == -1) {
2080#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002081 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002082 if (!tcp)
2083 continue;
2084 pfd = tcp->pfd;
2085 if (pfd == -1)
2086 continue;
2087 break;
2088#ifndef HAVE_POLLABLE_PROCFS
2089 }
2090 /* fall through ... */
2091#endif /* !HAVE_POLLABLE_PROCFS */
2092 default:
2093#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002094#ifdef POLL_HACK
2095 /* On some systems (e.g. UnixWare) we get too much ugly
2096 "unfinished..." stuff when multiple proceses are in
2097 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002098
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002099 if (in_syscall) {
2100 struct pollfd pv;
2101 tcp = in_syscall;
2102 in_syscall = NULL;
2103 pv.fd = tcp->pfd;
2104 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002105 what = poll(&pv, 1, 1);
2106 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002107 if (interrupted)
2108 return 0;
2109 continue;
2110 }
2111 else if (what == 1 && pv.revents & POLLWANT) {
2112 goto FOUND;
2113 }
2114 }
2115#endif
2116
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002117 if (poll(pollv, nprocs, INFTIM) < 0) {
2118 if (interrupted)
2119 return 0;
2120 continue;
2121 }
2122#else /* !HAVE_POLLABLE_PROCFS */
2123 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2124 if (interrupted)
2125 return 0;
2126 continue;
2127 }
2128#endif /* !HAVE_POLLABLE_PROCFS */
2129 pfd = choose_pfd();
2130 if (pfd == -1)
2131 continue;
2132 break;
2133 }
2134
2135 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002136 tcp = pfd2tcb(pfd);
2137 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002138 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002139 }
John Hughesb6643082002-05-23 11:02:22 +00002140#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002141 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002142#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002143 /* Get the status of the process. */
2144 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002145#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002146 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002147#else /* FREEBSD */
2148 /* Thanks to some scheduling mystery, the first poller
2149 sometimes waits for the already processed end of fork
2150 event. Doing a non blocking poll here solves the problem. */
2151 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002152 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002153 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002154 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002155#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002156 ioctl_errno = errno;
2157#ifndef HAVE_POLLABLE_PROCFS
2158 if (proc_poll_pipe[0] != -1) {
2159 if (ioctl_result < 0)
2160 kill(poller_pid, SIGKILL);
2161 else
2162 kill(poller_pid, SIGUSR1);
2163 }
2164#endif /* !HAVE_POLLABLE_PROCFS */
2165 }
2166 if (interrupted)
2167 return 0;
2168
2169 if (interactive)
2170 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2171
2172 if (ioctl_result < 0) {
2173 /* Find out what happened if it failed. */
2174 switch (ioctl_errno) {
2175 case EINTR:
2176 case EBADF:
2177 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002178#ifdef FREEBSD
2179 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002180#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002181 case ENOENT:
2182 droptcb(tcp);
2183 continue;
2184 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002185 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 }
2187 }
2188
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002189#ifdef FREEBSD
2190 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2191 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002192 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002193 continue;
2194 }
Roland McGrath553a6092002-12-16 20:40:39 +00002195#endif
2196
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 /* clear the just started flag */
2198 tcp->flags &= ~TCB_STARTUP;
2199
2200 /* set current output file */
2201 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002202 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203
2204 if (cflag) {
2205 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002206#ifdef FREEBSD
2207 char buf[1024];
2208 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209
Denys Vlasenko5d645812011-08-20 12:48:18 +02002210 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2211 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002212 buf[len] = '\0';
2213 sscanf(buf,
2214 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2215 &stime.tv_sec, &stime.tv_usec);
2216 } else
2217 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002218#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002219 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2220 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002221#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002222 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2223 tcp->stime = stime;
2224 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002225 what = tcp->status.PR_WHAT;
2226 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002227#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002228 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002229 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2230 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002232 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 }
2234 }
2235 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002236#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002238#ifdef POLL_HACK
2239 in_syscall = tcp;
2240#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002241 case PR_SYSEXIT:
2242 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002243 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244 }
2245 break;
2246 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002247 if (cflag != CFLAG_ONLY_STATS
2248 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002249 printleader(tcp);
2250 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002251 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002252 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002253#ifdef PR_INFO
2254 if (tcp->status.PR_INFO.si_signo == what) {
2255 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002256 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002257 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002258 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002259 }
2260#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002261 }
2262 break;
2263 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002264 if (cflag != CFLAGS_ONLY_STATS
2265 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 printleader(tcp);
2267 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002268 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002269 }
2270 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002271#ifdef FREEBSD
2272 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002273 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002274#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002275 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002276 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277 break;
2278 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002279 /* Remember current print column before continuing. */
2280 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002281 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002282#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002283 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002284#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002285 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002286#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002287 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002288 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289 }
2290 }
2291 return 0;
2292}
2293
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002294#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002295
Roland McGratheb9e2e82009-06-02 16:49:22 -07002296static int
2297trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298{
2299 int pid;
2300 int wait_errno;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002301 int status, sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002302 struct tcb *tcp;
2303#ifdef LINUX
2304 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002305 struct rusage *rup = cflag ? &ru : NULL;
2306# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002307 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002308# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002309#endif /* LINUX */
2310
Roland McGratheb9e2e82009-06-02 16:49:22 -07002311 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002312 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002313 return 0;
2314 if (interactive)
2315 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002316#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002317# ifdef __WALL
2318 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002319 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002320 /* this kernel does not support __WALL */
2321 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002322 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002323 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002324 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002325 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002326 pid = wait4(-1, &status, __WCLONE, rup);
2327 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002328 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002329 }
2330 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002331# else
2332 pid = wait4(-1, &status, 0, rup);
2333# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334#endif /* LINUX */
2335#ifdef SUNOS4
2336 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002337#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002338 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002339 if (interactive)
2340 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002342 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002343 switch (wait_errno) {
2344 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002346 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 /*
2348 * We would like to verify this case
2349 * but sometimes a race in Solbourne's
2350 * version of SunOS sometimes reports
2351 * ECHILD before sending us SIGCHILD.
2352 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002353 return 0;
2354 default:
2355 errno = wait_errno;
2356 perror("strace: wait");
2357 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002358 }
2359 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002360 if (pid == popen_pid) {
2361 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002362 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002363 continue;
2364 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002365 if (debug) {
2366 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2367#ifdef LINUX
2368 unsigned ev = (unsigned)status >> 16;
2369 if (ev) {
2370 static const char *const event_names[] = {
2371 [PTRACE_EVENT_CLONE] = "CLONE",
2372 [PTRACE_EVENT_FORK] = "FORK",
2373 [PTRACE_EVENT_VFORK] = "VFORK",
2374 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2375 [PTRACE_EVENT_EXEC] = "EXEC",
2376 [PTRACE_EVENT_EXIT] = "EXIT",
2377 };
2378 const char *e;
2379 if (ev < ARRAY_SIZE(event_names))
2380 e = event_names[ev];
2381 else {
2382 sprintf(buf, "?? (%u)", ev);
2383 e = buf;
2384 }
2385 fprintf(stderr, " PTRACE_EVENT_%s", e);
2386 }
2387#endif
2388 strcpy(buf, "???");
2389 if (WIFSIGNALED(status))
2390#ifdef WCOREDUMP
2391 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2392 WCOREDUMP(status) ? "core," : "",
2393 signame(WTERMSIG(status)));
2394#else
2395 sprintf(buf, "WIFSIGNALED,sig=%s",
2396 signame(WTERMSIG(status)));
2397#endif
2398 if (WIFEXITED(status))
2399 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2400 if (WIFSTOPPED(status))
2401 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002402#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002403 if (WIFCONTINUED(status))
2404 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002405#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002406 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2407 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002408
2409 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002410 tcp = pid2tcb(pid);
2411 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002412#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002413 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002414 /* This is needed to go with the CLONE_PTRACE
2415 changes in process.c/util.c: we might see
2416 the child's initial trap before we see the
2417 parent return from the clone syscall.
2418 Leave the child suspended until the parent
2419 returns from its system call. Only then
2420 will we have the association of parent and
2421 child so that we know how to do clearbpt
2422 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002423 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002424 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002425 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002426 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002427 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002428 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002429 else
2430 /* This can happen if a clone call used
2431 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002432#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002433 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002434 if (WIFSTOPPED(status))
2435 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002436 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002437 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002438 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002439 /* set current output file */
2440 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002441 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002442#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002443 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2445 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002446 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002447#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002448
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002450 if (pid == strace_child)
2451 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002452 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002453 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2454 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002455#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002456 tprintf("+++ killed by %s %s+++",
2457 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002458 WCOREDUMP(status) ? "(core dumped) " : "");
2459#else
2460 tprintf("+++ killed by %s +++",
2461 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002462#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002463 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002464 }
2465 droptcb(tcp);
2466 continue;
2467 }
2468 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002469 if (pid == strace_child)
2470 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002471 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002472 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002473 tprintf(" <unfinished ... exit status %d>\n",
2474 WEXITSTATUS(status));
2475 tcp_last = NULL;
2476 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002477 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2478 printleader(tcp);
2479 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2480 printtrailer();
2481 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002482 droptcb(tcp);
2483 continue;
2484 }
2485 if (!WIFSTOPPED(status)) {
2486 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2487 droptcb(tcp);
2488 continue;
2489 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002490
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002491 /* Is this the very first time we see this tracee stopped? */
2492 if (tcp->flags & TCB_STARTUP) {
2493 if (debug)
2494 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002496 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002497 /*
2498 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002499 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002500 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002501 if (clearbpt(tcp) < 0) {
2502 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002503 droptcb(tcp);
2504 cleanup();
2505 return -1;
2506 }
2507 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002508#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002509 if (ptrace_setoptions) {
2510 if (debug)
2511 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2512 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2513 if (errno != ESRCH) {
2514 /* Should never happen, really */
2515 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002516 }
2517 }
2518 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002519#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002520 }
2521
2522 if (((unsigned)status >> 16) != 0) {
2523 /* Ptrace event (we ignore all of them for now) */
2524 goto restart_tracee_with_sig_0;
2525 }
2526
2527 sig = WSTOPSIG(status);
2528
2529 /* Is this post-attach SIGSTOP?
2530 * Interestingly, the process may stop
2531 * with STOPSIG equal to some other signal
2532 * than SIGSTOP if we happend to attach
2533 * just before the process takes a signal.
2534 */
2535 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2536 if (debug)
2537 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2538 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002539 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 }
2541
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002542 if (sig != syscall_trap_sig) {
2543 if (sig == SIGSTOP &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 (tcp->flags & TCB_SIGTRAPPED)) {
2545 /*
2546 * Trapped attempt to block SIGTRAP
2547 * Hope we are back in control now.
2548 */
2549 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002550 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002552 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002553 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002554 siginfo_t si;
2555#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002556 long pc = 0;
2557 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002558
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002559 upeek(tcp, PT_CR_IPSR, &psr);
2560 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002561
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002562# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002563 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002564# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002565# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002566#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002567# define PC_FORMAT_STR ""
2568# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002569#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002570 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002571 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002572 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002573 printsiginfo(&si, verbose(tcp));
2574 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002575 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002576 PC_FORMAT_ARG);
2577 } else
2578 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002579 strsignal(sig),
2580 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002581 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002582 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002583 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002584 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002585 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002586
2587 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002588 if (interrupted)
2589 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002590
2591 /* This should be syscall entry or exit.
2592 * (Or it still can be that pesky post-execve SIGTRAP!)
2593 * Handle it.
2594 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002595 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2596 /* ptrace() failed in trace_syscall() with ESRCH.
2597 * Likely a result of process disappearing mid-flight.
2598 * Observed case: exit_group() terminating
2599 * all processes in thread group. In this case, threads
2600 * "disappear" in an unpredictable moment without any
2601 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002602 */
2603 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002604 if (tcp_last) {
2605 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002606 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002607 */
2608 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002609 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002610 printtrailer();
2611 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002612 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002613 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002614 ptrace(PTRACE_KILL,
2615 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002616 droptcb(tcp);
2617 }
2618 continue;
2619 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002620 restart_tracee_with_sig_0:
2621 sig = 0;
2622 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002623 /* Remember current print column before continuing. */
2624 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002625 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002626 cleanup();
2627 return -1;
2628 }
2629 }
2630 return 0;
2631}
2632
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002633#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002634
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002635void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637{
2638 va_list args;
2639
Andreas Schwabe5355de2009-10-27 16:56:43 +01002640 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002641 if (outf) {
2642 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002643 if (n < 0) {
2644 if (outf != stderr)
2645 perror(outfname == NULL
2646 ? "<writing to pipe>" : outfname);
2647 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002648 curcol += n;
2649 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002650 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002651}
2652
2653void
2654tprints(const char *str)
2655{
2656 if (outf) {
2657 int n = fputs(str, outf);
2658 if (n >= 0) {
2659 curcol += strlen(str);
2660 return;
2661 }
2662 if (outf != stderr)
2663 perror(outfname == NULL
2664 ? "<writing to pipe>" : outfname);
2665 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002666}
2667
2668void
Denys Vlasenko12014262011-05-30 14:00:14 +02002669printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002671 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002672 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002673 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002674 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002675 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002676 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002677 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002678 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002679 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002680 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002681 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002682 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002683 }
2684 curcol = 0;
2685 if ((followfork == 1 || pflag_seen > 1) && outfname)
2686 tprintf("%-5d ", tcp->pid);
2687 else if (nprocs > 1 && !outfname)
2688 tprintf("[pid %5u] ", tcp->pid);
2689 if (tflag) {
2690 char str[sizeof("HH:MM:SS")];
2691 struct timeval tv, dtv;
2692 static struct timeval otv;
2693
2694 gettimeofday(&tv, NULL);
2695 if (rflag) {
2696 if (otv.tv_sec == 0)
2697 otv = tv;
2698 tv_sub(&dtv, &tv, &otv);
2699 tprintf("%6ld.%06ld ",
2700 (long) dtv.tv_sec, (long) dtv.tv_usec);
2701 otv = tv;
2702 }
2703 else if (tflag > 2) {
2704 tprintf("%ld.%06ld ",
2705 (long) tv.tv_sec, (long) tv.tv_usec);
2706 }
2707 else {
2708 time_t local = tv.tv_sec;
2709 strftime(str, sizeof(str), "%T", localtime(&local));
2710 if (tflag > 1)
2711 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2712 else
2713 tprintf("%s ", str);
2714 }
2715 }
2716 if (iflag)
2717 printcall(tcp);
2718}
2719
2720void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002721tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002722{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002723 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002724 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002725}
2726
2727void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002728printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002729{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002730 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002731 tcp_last = NULL;
2732}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002733
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002734#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002735
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002736int
2737mp_ioctl(int fd, int cmd, void *arg, int size)
2738{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002739 struct iovec iov[2];
2740 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002741
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002742 iov[0].iov_base = &cmd;
2743 iov[0].iov_len = sizeof cmd;
2744 if (arg) {
2745 ++n;
2746 iov[1].iov_base = arg;
2747 iov[1].iov_len = size;
2748 }
Roland McGrath553a6092002-12-16 20:40:39 +00002749
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002750 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002751}
2752
2753#endif