blob: bbb7ac17272d13474e70cc9d16d65a6fa3dff30c [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>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
52# if defined __NR_tgkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020053# define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# elif defined __NR_tkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020055# define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000056# else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenkob63256e2011-06-07 12:13:24 +020061# define my_tgkill(pid, tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000062# endif
63#endif
64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000065#if defined(IA64) && defined(LINUX)
66# include <asm/ptrace_offsets.h>
67#endif
68
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000069#ifdef USE_PROCFS
70#include <poll.h>
71#endif
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#ifdef SVR4
74#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000075#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000076#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#include <sys/uio.h>
78#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000080#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000082extern int optind;
83extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085
Roland McGrath41c48222008-07-18 00:25:10 +000086int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020087unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020088/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020089static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000090int dtime = 0, xflag = 0, qflag = 0;
91cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000092static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000093/*
94 * daemonized_tracer supports -D option.
95 * With this option, strace forks twice.
96 * Unlike normal case, with -D *grandparent* process exec's,
97 * becoming a traced process. Child exits (this prevents traced process
98 * from having children it doesn't expect to have), and grandchild
99 * attaches to grandparent similarly to strace -p PID.
100 * This allows for more transparent interaction in cases
101 * when process and its parent are communicating via signals,
102 * wait() etc. Without -D, strace process gets lodged in between,
103 * disrupting parent<->child link.
104 */
105static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000107/* Sometimes we want to print only succeeding syscalls. */
108int not_failing_only = 0;
109
Grant Edwards8a082772011-04-07 20:25:40 +0000110/* Show path associated with fd arguments */
111int show_fd_path = 0;
112
113/* are we filtering traces based on paths? */
114int tracing_paths = 0;
115
Dmitry V. Levina6809652008-11-10 17:14:58 +0000116static int exit_code = 0;
117static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200118static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000120static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121uid_t run_uid;
122gid_t run_gid;
123
124int acolumn = DEFAULT_ACOLUMN;
125int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000129struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200130static unsigned int nprocs, tcbtabsize;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000131const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Andreas Schwabe5355de2009-10-27 16:56:43 +0100133static int detach(struct tcb *tcp, int sig);
134static int trace(void);
135static void cleanup(void);
136static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137static sigset_t empty_set, blocked_set;
138
139#ifdef HAVE_SIG_ATOMIC_T
140static volatile sig_atomic_t interrupted;
141#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143#endif /* !HAVE_SIG_ATOMIC_T */
144
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000145#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
Andreas Schwabe5355de2009-10-27 16:56:43 +0100147static struct tcb *pfd2tcb(int pfd);
148static void reaper(int sig);
149static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000150static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#ifndef HAVE_POLLABLE_PROCFS
153
Andreas Schwabe5355de2009-10-27 16:56:43 +0100154static void proc_poll_open(void);
155static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156
157struct proc_pollfd {
158 int fd;
159 int revents;
160 int pid;
161};
162
163static int poller_pid;
164static int proc_poll_pipe[2] = { -1, -1 };
165
166#endif /* !HAVE_POLLABLE_PROCFS */
167
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000168#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000169#define POLLWANT POLLWRNORM
170#else
171#define POLLWANT POLLPRI
172#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000173#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174
175static void
176usage(ofp, exitval)
177FILE *ofp;
178int exitval;
179{
180 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000181usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000183 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200184 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000185 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200187-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-f -- follow forks, -ff -- with output into separate files\n\
189-F -- attempt to follow vforks, -h -- print help message\n\
190-i -- print instruction pointer at time of syscall\n\
191-q -- suppress messages about attaching, detaching, etc.\n\
192-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
193-T -- print time spent in each syscall, -V -- print version\n\
194-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
195-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000196-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197-a column -- alignment COLUMN for printing syscall results (default %d)\n\
198-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
199 options: trace, abbrev, verbose, raw, signal, read, or write\n\
200-o file -- send trace output to FILE instead of stderr\n\
201-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
202-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000203-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
205-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
206-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000207-E var=val -- put var=val in the environment for command\n\
208-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000209-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000210" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000211-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000212 */
213, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214 exit(exitval);
215}
216
Denys Vlasenko75422762011-05-27 14:36:01 +0200217static void die(void) __attribute__ ((noreturn));
218static void die(void)
219{
220 if (strace_tracer_pid == getpid()) {
221 cflag = 0;
222 cleanup();
223 }
224 exit(1);
225}
226
227static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200228{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000229 fflush(NULL);
230 fprintf(stderr, "%s: ", progname);
231 vfprintf(stderr, fmt, p);
232 if (err_no)
233 fprintf(stderr, ": %s\n", strerror(err_no));
234 else
235 putc('\n', stderr);
236 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200237}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200238
Denys Vlasenko75422762011-05-27 14:36:01 +0200239void error_msg(const char *fmt, ...)
240{
241 va_list p;
242 va_start(p, fmt);
243 verror_msg(0, fmt, p);
244 va_end(p);
245}
246
247void error_msg_and_die(const char *fmt, ...)
248{
249 va_list p;
250 va_start(p, fmt);
251 verror_msg(0, fmt, p);
252 die();
253}
254
255void perror_msg(const char *fmt, ...)
256{
257 va_list p;
258 va_start(p, fmt);
259 verror_msg(errno, fmt, p);
260 va_end(p);
261}
262
263void perror_msg_and_die(const char *fmt, ...)
264{
265 va_list p;
266 va_start(p, fmt);
267 verror_msg(errno, fmt, p);
268 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200269}
270
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000271#ifdef SVR4
272#ifdef MIPS
273void
274foobar()
275{
276}
277#endif /* MIPS */
278#endif /* SVR4 */
279
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400280/* Glue for systems without a MMU that cannot provide fork() */
281#ifdef HAVE_FORK
282# define strace_vforked 0
283#else
284# define strace_vforked 1
285# define fork() vfork()
286#endif
287
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200288static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000289set_cloexec_flag(int fd)
290{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200291 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000292
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200293 flags = fcntl(fd, F_GETFD);
294 if (flags < 0) {
295 /* Can happen only if fd is bad.
296 * Should never happen: if it does, we have a bug
297 * in the caller. Therefore we just abort
298 * instead of propagating the error.
299 */
300 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000301 }
302
303 newflags = flags | FD_CLOEXEC;
304 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200305 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000306
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200307 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000308}
309
310/*
311 * When strace is setuid executable, we have to swap uids
312 * before and after filesystem and process management operations.
313 */
314static void
315swap_uid(void)
316{
317#ifndef SVR4
318 int euid = geteuid(), uid = getuid();
319
320 if (euid != uid && setreuid(euid, uid) < 0)
321 {
322 fprintf(stderr, "%s: setreuid: %s\n",
323 progname, strerror(errno));
324 exit(1);
325 }
326#endif
327}
328
Roland McGrath4bfa6262007-07-05 20:03:16 +0000329#if _LFS64_LARGEFILE
330# define fopen_for_output fopen64
331#else
332# define fopen_for_output fopen
333#endif
334
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000335static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200336strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000337{
338 FILE *fp;
339
340 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200341 fp = fopen_for_output(path, "w");
342 if (!fp)
343 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000344 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200345 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000346 return fp;
347}
348
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200349static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000350
351#ifndef _PATH_BSHELL
352# define _PATH_BSHELL "/bin/sh"
353#endif
354
355/*
356 * We cannot use standard popen(3) here because we have to distinguish
357 * popen child process from other processes we trace, and standard popen(3)
358 * does not export its child's pid.
359 */
360static FILE *
361strace_popen(const char *command)
362{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200363 FILE *fp;
364 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000365
366 swap_uid();
367 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200368 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000369
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200370 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000371
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200372 popen_pid = vfork();
373 if (popen_pid == -1)
374 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000375
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200376 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000377 /* child */
378 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200379 if (fds[0] != 0) {
380 if (dup2(fds[0], 0))
381 perror_msg_and_die("dup2");
382 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000383 }
384 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200385 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000386 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200387
388 /* parent */
389 close(fds[0]);
390 swap_uid();
391 fp = fdopen(fds[1], "w");
392 if (!fp)
393 error_msg_and_die("Out of memory");
394 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000395}
396
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200397static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000398newoutf(struct tcb *tcp)
399{
400 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000401 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000402 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200403 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000404 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000405}
406
Roland McGrath02203312007-06-11 22:06:31 +0000407static void
408startup_attach(void)
409{
410 int tcbi;
411 struct tcb *tcp;
412
413 /*
414 * Block user interruptions as we would leave the traced
415 * process stopped (process state T) if we would terminate in
416 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200417 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000418 */
419 if (interactive)
420 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
421
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000422 if (daemonized_tracer) {
423 pid_t pid = fork();
424 if (pid < 0) {
425 _exit(1);
426 }
427 if (pid) { /* parent */
428 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200429 * Wait for grandchild to attach to straced process
430 * (grandparent). Grandchild SIGKILLs us after it attached.
431 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000432 * it proceeds to exec the straced program.
433 */
434 pause();
435 _exit(0); /* paranoia */
436 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200437 /* grandchild */
438 /* We will be the tracer process. Remember our new pid: */
439 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000440 }
441
Roland McGrath02203312007-06-11 22:06:31 +0000442 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
443 tcp = tcbtab[tcbi];
444 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
445 continue;
446#ifdef LINUX
447 if (tcp->flags & TCB_CLONE_THREAD)
448 continue;
449#endif
450 /* Reinitialize the output since it may have changed. */
451 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200452 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000453
454#ifdef USE_PROCFS
455 if (proc_open(tcp, 1) < 0) {
456 fprintf(stderr, "trouble opening proc file\n");
457 droptcb(tcp);
458 continue;
459 }
460#else /* !USE_PROCFS */
461# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000462 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000463 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000464 DIR *dir;
465
466 sprintf(procdir, "/proc/%d/task", tcp->pid);
467 dir = opendir(procdir);
468 if (dir != NULL) {
469 unsigned int ntid = 0, nerr = 0;
470 struct dirent *de;
471 int tid;
472 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000473 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000474 continue;
475 tid = atoi(de->d_name);
476 if (tid <= 0)
477 continue;
478 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000479 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000480 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000481 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000482 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800483 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000484 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000485 tcp->parent = tcbtab[tcbi];
486 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000487 if (interactive) {
488 sigprocmask(SIG_SETMASK, &empty_set, NULL);
489 if (interrupted)
490 return;
491 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
492 }
Roland McGrath02203312007-06-11 22:06:31 +0000493 }
494 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000495 ntid -= nerr;
496 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000497 perror("attach: ptrace(PTRACE_ATTACH, ...)");
498 droptcb(tcp);
499 continue;
500 }
501 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000502 fprintf(stderr, ntid > 1
503? "Process %u attached with %u threads - interrupt to quit\n"
504: "Process %u attached - interrupt to quit\n",
505 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000506 }
507 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000508 } /* if (opendir worked) */
509 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000510# endif
511 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
512 perror("attach: ptrace(PTRACE_ATTACH, ...)");
513 droptcb(tcp);
514 continue;
515 }
516 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000517
518 if (daemonized_tracer) {
519 /*
520 * It is our grandparent we trace, not a -p PID.
521 * Don't want to just detach on exit, so...
522 */
523 tcp->flags &= ~TCB_ATTACHED;
524 /*
525 * Make parent go away.
526 * Also makes grandparent's wait() unblock.
527 */
528 kill(getppid(), SIGKILL);
529 }
530
Roland McGrath02203312007-06-11 22:06:31 +0000531#endif /* !USE_PROCFS */
532 if (!qflag)
533 fprintf(stderr,
534 "Process %u attached - interrupt to quit\n",
535 tcp->pid);
536 }
537
538 if (interactive)
539 sigprocmask(SIG_SETMASK, &empty_set, NULL);
540}
541
542static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200543startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000544{
545 struct stat statbuf;
546 const char *filename;
547 char pathname[MAXPATHLEN];
548 int pid = 0;
549 struct tcb *tcp;
550
551 filename = argv[0];
552 if (strchr(filename, '/')) {
553 if (strlen(filename) > sizeof pathname - 1) {
554 errno = ENAMETOOLONG;
555 perror("strace: exec");
556 exit(1);
557 }
558 strcpy(pathname, filename);
559 }
560#ifdef USE_DEBUGGING_EXEC
561 /*
562 * Debuggers customarily check the current directory
563 * first regardless of the path but doing that gives
564 * security geeks a panic attack.
565 */
566 else if (stat(filename, &statbuf) == 0)
567 strcpy(pathname, filename);
568#endif /* USE_DEBUGGING_EXEC */
569 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000570 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000571 int m, n, len;
572
573 for (path = getenv("PATH"); path && *path; path += m) {
574 if (strchr(path, ':')) {
575 n = strchr(path, ':') - path;
576 m = n + 1;
577 }
578 else
579 m = n = strlen(path);
580 if (n == 0) {
581 if (!getcwd(pathname, MAXPATHLEN))
582 continue;
583 len = strlen(pathname);
584 }
585 else if (n > sizeof pathname - 1)
586 continue;
587 else {
588 strncpy(pathname, path, n);
589 len = n;
590 }
591 if (len && pathname[len - 1] != '/')
592 pathname[len++] = '/';
593 strcpy(pathname + len, filename);
594 if (stat(pathname, &statbuf) == 0 &&
595 /* Accept only regular files
596 with some execute bits set.
597 XXX not perfect, might still fail */
598 S_ISREG(statbuf.st_mode) &&
599 (statbuf.st_mode & 0111))
600 break;
601 }
602 }
603 if (stat(pathname, &statbuf) < 0) {
604 fprintf(stderr, "%s: %s: command not found\n",
605 progname, filename);
606 exit(1);
607 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000608 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000609 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000610 perror("strace: fork");
611 cleanup();
612 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000613 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200614 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
615 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000616 ) {
617 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000618#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200619 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000620#ifdef MIPS
621 /* Kludge for SGI, see proc_open for details. */
622 sa.sa_handler = foobar;
623 sa.sa_flags = 0;
624 sigemptyset(&sa.sa_mask);
625 sigaction(SIGINT, &sa, NULL);
626#endif /* MIPS */
627#ifndef FREEBSD
628 pause();
629#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000630 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000631#endif /* FREEBSD */
632#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200633 if (outf != stderr)
634 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000635
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000636 if (!daemonized_tracer) {
637 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
638 perror("strace: ptrace(PTRACE_TRACEME, ...)");
639 exit(1);
640 }
641 if (debug)
642 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000643 }
Roland McGrath02203312007-06-11 22:06:31 +0000644
645 if (username != NULL || geteuid() == 0) {
646 uid_t run_euid = run_uid;
647 gid_t run_egid = run_gid;
648
649 if (statbuf.st_mode & S_ISUID)
650 run_euid = statbuf.st_uid;
651 if (statbuf.st_mode & S_ISGID)
652 run_egid = statbuf.st_gid;
653
654 /*
655 * It is important to set groups before we
656 * lose privileges on setuid.
657 */
658 if (username != NULL) {
659 if (initgroups(username, run_gid) < 0) {
660 perror("initgroups");
661 exit(1);
662 }
663 if (setregid(run_gid, run_egid) < 0) {
664 perror("setregid");
665 exit(1);
666 }
667 if (setreuid(run_uid, run_euid) < 0) {
668 perror("setreuid");
669 exit(1);
670 }
671 }
672 }
673 else
674 setreuid(run_uid, run_uid);
675
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 if (!daemonized_tracer) {
677 /*
678 * Induce an immediate stop so that the parent
679 * will resume us with PTRACE_SYSCALL and display
680 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400681 * Unless of course we're on a no-MMU system where
682 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400684 if (!strace_vforked)
685 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000686 } else {
687 struct sigaction sv_sigchld;
688 sigaction(SIGCHLD, NULL, &sv_sigchld);
689 /*
690 * Make sure it is not SIG_IGN, otherwise wait
691 * will not block.
692 */
693 signal(SIGCHLD, SIG_DFL);
694 /*
695 * Wait for grandchild to attach to us.
696 * It kills child after that, and wait() unblocks.
697 */
698 alarm(3);
699 wait(NULL);
700 alarm(0);
701 sigaction(SIGCHLD, &sv_sigchld, NULL);
702 }
Roland McGrath02203312007-06-11 22:06:31 +0000703#endif /* !USE_PROCFS */
704
705 execv(pathname, argv);
706 perror("strace: exec");
707 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000708 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000709
710 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200711 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
712 strace_tracer_pid = getpid();
713
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000715 if (daemonized_tracer) {
716 /* We want subsequent startup_attach() to attach to it. */
717 tcp->flags |= TCB_ATTACHED;
718 }
Roland McGrath02203312007-06-11 22:06:31 +0000719#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000720 if (proc_open(tcp, 0) < 0) {
721 fprintf(stderr, "trouble opening proc file\n");
722 cleanup();
723 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000724 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000725#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000726}
727
Wang Chaob13c0de2010-11-12 17:25:19 +0800728#ifdef LINUX
729/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000730 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800731 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000732 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800733 */
734static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200735test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800736{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000737 int pid, expected_grandchild = 0, found_grandchild = 0;
738 const unsigned int test_options = PTRACE_O_TRACECLONE |
739 PTRACE_O_TRACEFORK |
740 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800741
742 if ((pid = fork()) < 0)
743 return -1;
744 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000745 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800746 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800747 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000748 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800749 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000750
751 while (1) {
752 int status, tracee_pid;
753
754 tracee_pid = wait(&status);
755 if (tracee_pid == -1) {
756 if (errno == EINTR)
757 continue;
758 else if (errno == ECHILD)
759 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200760 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000761 return -1;
762 }
763 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000764 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000765 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
766 errno != ESRCH)
767 kill(tracee_pid, SIGKILL);
768 }
769 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000770 switch (WSTOPSIG(status)) {
771 case SIGSTOP:
772 if (ptrace(PTRACE_SETOPTIONS, pid,
773 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000774 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800775 return -1;
776 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000777 break;
778 case SIGTRAP:
779 if (status >> 16 == PTRACE_EVENT_FORK) {
780 long msg = 0;
781
782 if (ptrace(PTRACE_GETEVENTMSG, pid,
783 NULL, (long) &msg) == 0)
784 expected_grandchild = msg;
785 }
786 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800787 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000788 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
789 errno != ESRCH)
790 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800791 }
792 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000793 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200794 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800795 return 0;
796}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200797
798/*
799 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
800 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
801 * and then see whether it will stop with (SIGTRAP | 0x80).
802 *
803 * Use of this option enables correct handling of user-generated SIGTRAPs,
804 * and SIGTRAPs generated by special instructions such as int3 on x86:
805 * _start: .globl _start
806 * int3
807 * movl $42, %ebx
808 * movl $1, %eax
809 * int $0x80
810 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
811 */
812static void
813test_ptrace_setoptions_for_all(void)
814{
815 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
816 int pid;
817 int it_worked = 0;
818
819 pid = fork();
820 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200821 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200822
823 if (pid == 0) {
824 pid = getpid();
825 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200826 /* Note: exits with exitcode 1 */
827 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200828 kill(pid, SIGSTOP);
829 _exit(0); /* parent should see entry into this syscall */
830 }
831
832 while (1) {
833 int status, tracee_pid;
834
835 errno = 0;
836 tracee_pid = wait(&status);
837 if (tracee_pid <= 0) {
838 if (errno == EINTR)
839 continue;
840 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200841 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200842 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200843 if (WIFEXITED(status)) {
844 if (WEXITSTATUS(status) == 0)
845 break;
846 /* PTRACE_TRACEME failed in child. This is fatal. */
847 exit(1);
848 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200849 if (!WIFSTOPPED(status)) {
850 kill(pid, SIGKILL);
851 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
852 }
853 if (WSTOPSIG(status) == SIGSTOP) {
854 /*
855 * We don't check "options aren't accepted" error.
856 * If it happens, we'll never get (SIGTRAP | 0x80),
857 * and thus will decide to not use the option.
858 * IOW: the outcome of the test will be correct.
859 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200860 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
861 if (errno != EINVAL)
862 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200863 }
864 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
865 it_worked = 1;
866 }
867 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
868 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200869 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200870 }
871 }
872
873 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200874 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200875 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200876 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200877 fprintf(stderr, "ptrace_setoptions = %#x\n",
878 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200879 return;
880 }
881
882 fprintf(stderr,
883 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
884}
Wang Chaob13c0de2010-11-12 17:25:19 +0800885#endif
886
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000887int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000888main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 struct tcb *tcp;
891 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000892 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 struct sigaction sa;
894
895 static char buf[BUFSIZ];
896
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000897 progname = argv[0] ? argv[0] : "strace";
898
Denys Vlasenko75422762011-05-27 14:36:01 +0200899 strace_tracer_pid = getpid();
900
Roland McGrathee9d4352002-12-18 04:16:10 +0000901 /* Allocate the initial tcbtab. */
902 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000903 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000904 fprintf(stderr, "%s: out of memory\n", progname);
905 exit(1);
906 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000907 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000908 fprintf(stderr, "%s: out of memory\n", progname);
909 exit(1);
910 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000911 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
912 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
913
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914 outf = stderr;
915 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000916 set_sortby(DEFAULT_SORTBY);
917 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000918 qualify("trace=all");
919 qualify("abbrev=all");
920 qualify("verbose=all");
921 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000923 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000924#ifndef USE_PROCFS
925 "D"
926#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000927 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 switch (c) {
929 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000930 if (cflag == CFLAG_BOTH) {
931 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
932 progname);
933 exit(1);
934 }
935 cflag = CFLAG_ONLY_STATS;
936 break;
937 case 'C':
938 if (cflag == CFLAG_ONLY_STATS) {
939 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
940 progname);
941 exit(1);
942 }
943 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 break;
945 case 'd':
946 debug++;
947 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000948#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000949 case 'D':
950 daemonized_tracer = 1;
951 break;
952#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000953 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000954 optF = 1;
955 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956 case 'f':
957 followfork++;
958 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959 case 'h':
960 usage(stdout, 0);
961 break;
962 case 'i':
963 iflag++;
964 break;
965 case 'q':
966 qflag++;
967 break;
968 case 'r':
969 rflag++;
970 tflag++;
971 break;
972 case 't':
973 tflag++;
974 break;
975 case 'T':
976 dtime++;
977 break;
978 case 'x':
979 xflag++;
980 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000981 case 'y':
982 show_fd_path = 1;
983 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 case 'v':
985 qualify("abbrev=none");
986 break;
987 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000988 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989 exit(0);
990 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000991 case 'z':
992 not_failing_only = 1;
993 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 case 'a':
995 acolumn = atoi(optarg);
996 break;
997 case 'e':
998 qualify(optarg);
999 break;
1000 case 'o':
1001 outfname = strdup(optarg);
1002 break;
1003 case 'O':
1004 set_overhead(atoi(optarg));
1005 break;
1006 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +00001007 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 fprintf(stderr, "%s: Invalid process id: %s\n",
1009 progname, optarg);
1010 break;
1011 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001012 if (pid == strace_tracer_pid) {
Wichert Akkerman54a47671999-10-17 00:57:34 +00001013 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 break;
1015 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001016 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 tcp->flags |= TCB_ATTACHED;
1018 pflag_seen++;
1019 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001020 case 'P':
1021 tracing_paths = 1;
1022 if (pathtrace_select(optarg)) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001023 fprintf(stderr, "%s : failed to select path '%s'\n", progname, optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001024 exit(1);
1025 }
1026 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 case 's':
1028 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001029 if (max_strlen < 0) {
1030 fprintf(stderr,
1031 "%s: invalid -s argument: %s\n",
1032 progname, optarg);
1033 exit(1);
1034 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 break;
1036 case 'S':
1037 set_sortby(optarg);
1038 break;
1039 case 'u':
1040 username = strdup(optarg);
1041 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001042 case 'E':
1043 if (putenv(optarg) < 0) {
1044 fprintf(stderr, "%s: out of memory\n",
1045 progname);
1046 exit(1);
1047 }
1048 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 default:
1050 usage(stderr, 1);
1051 break;
1052 }
1053 }
1054
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001055 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001056 usage(stderr, 1);
1057
Wang Chaod322a4b2010-08-05 14:30:11 +08001058 if (pflag_seen && daemonized_tracer) {
1059 fprintf(stderr,
1060 "%s: -D and -p are mutually exclusive options\n",
1061 progname);
1062 exit(1);
1063 }
1064
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001065 if (!followfork)
1066 followfork = optF;
1067
Roland McGrathcb9def62006-04-25 07:48:03 +00001068 if (followfork > 1 && cflag) {
1069 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001070 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +00001071 progname);
1072 exit(1);
1073 }
1074
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 /* See if they want to run as another user. */
1076 if (username != NULL) {
1077 struct passwd *pent;
1078
1079 if (getuid() != 0 || geteuid() != 0) {
1080 fprintf(stderr,
1081 "%s: you must be root to use the -u option\n",
1082 progname);
1083 exit(1);
1084 }
1085 if ((pent = getpwnam(username)) == NULL) {
1086 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +00001087 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 exit(1);
1089 }
1090 run_uid = pent->pw_uid;
1091 run_gid = pent->pw_gid;
1092 }
1093 else {
1094 run_uid = getuid();
1095 run_gid = getgid();
1096 }
1097
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001098#ifdef LINUX
1099 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001100 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001101 fprintf(stderr,
1102 "Test for options supported by PTRACE_SETOPTIONS "
1103 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001104 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001105 }
1106 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001107 fprintf(stderr, "ptrace_setoptions = %#x\n",
1108 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001109 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001110 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001111#endif
1112
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 /* Check if they want to redirect the output. */
1114 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001115 /* See if they want to pipe the output. */
1116 if (outfname[0] == '|' || outfname[0] == '!') {
1117 /*
1118 * We can't do the <outfname>.PID funny business
1119 * when using popen, so prohibit it.
1120 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001121 if (followfork > 1)
1122 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1123 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001124 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001125 else if (followfork <= 1)
1126 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001127 }
1128
Roland McGrath37b9a662003-11-07 02:26:54 +00001129 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001130 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +00001131 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001134 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001135
Roland McGrath54cc1c82007-11-03 23:34:11 +00001136 /* Valid states here:
1137 optind < argc pflag_seen outfname interactive
1138 1 0 0 1
1139 0 1 0 1
1140 1 0 1 0
1141 0 1 1 1
1142 */
1143
1144 /* STARTUP_CHILD must be called before the signal handlers get
1145 installed below as they are inherited into the spawned process.
1146 Also we do not need to be protected by them as during interruption
1147 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1148 if (!pflag_seen)
1149 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 sigemptyset(&empty_set);
1152 sigemptyset(&blocked_set);
1153 sa.sa_handler = SIG_IGN;
1154 sigemptyset(&sa.sa_mask);
1155 sa.sa_flags = 0;
1156 sigaction(SIGTTOU, &sa, NULL);
1157 sigaction(SIGTTIN, &sa, NULL);
1158 if (interactive) {
1159 sigaddset(&blocked_set, SIGHUP);
1160 sigaddset(&blocked_set, SIGINT);
1161 sigaddset(&blocked_set, SIGQUIT);
1162 sigaddset(&blocked_set, SIGPIPE);
1163 sigaddset(&blocked_set, SIGTERM);
1164 sa.sa_handler = interrupt;
1165#ifdef SUNOS4
1166 /* POSIX signals on sunos4.1 are a little broken. */
1167 sa.sa_flags = SA_INTERRUPT;
1168#endif /* SUNOS4 */
1169 }
1170 sigaction(SIGHUP, &sa, NULL);
1171 sigaction(SIGINT, &sa, NULL);
1172 sigaction(SIGQUIT, &sa, NULL);
1173 sigaction(SIGPIPE, &sa, NULL);
1174 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001175#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 sa.sa_handler = reaper;
1177 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001178#else
1179 /* Make sure SIGCHLD has the default action so that waitpid
1180 definitely works without losing track of children. The user
1181 should not have given us a bogus state to inherit, but he might
1182 have. Arguably we should detect SIG_IGN here and pass it on
1183 to children, but probably noone really needs that. */
1184 sa.sa_handler = SIG_DFL;
1185 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001186#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001188 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001189 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001190
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 if (trace() < 0)
1192 exit(1);
1193 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001194 fflush(NULL);
1195 if (exit_code > 0xff) {
1196 /* Child was killed by a signal, mimic that. */
1197 exit_code &= 0xff;
1198 signal(exit_code, SIG_DFL);
1199 raise(exit_code);
1200 /* Paranoia - what if this signal is not fatal?
1201 Exit with 128 + signo then. */
1202 exit_code += 128;
1203 }
1204 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205}
1206
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001207static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001208expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001209{
1210 /* Allocate some more TCBs and expand the table.
1211 We don't want to relocate the TCBs because our
1212 callers have pointers and it would be a pain.
1213 So tcbtab is a table of pointers. Since we never
1214 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001215 int i = tcbtabsize;
1216 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1217 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1218 if (newtab == NULL || newtcbs == NULL)
1219 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001220 tcbtabsize *= 2;
1221 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001222 while (i < tcbtabsize)
1223 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001224}
1225
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001227alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228{
1229 int i;
1230 struct tcb *tcp;
1231
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001232 if (nprocs == tcbtabsize)
1233 expand_tcbtab();
1234
Roland McGrathee9d4352002-12-18 04:16:10 +00001235 for (i = 0; i < tcbtabsize; i++) {
1236 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001238 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001240 tcp->flags = TCB_INUSE | TCB_STARTUP;
1241 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 tcp->pfd = -1;
1243 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001244 if (command_options_parsed)
1245 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001246 return tcp;
1247 }
1248 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001249 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250}
1251
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001252#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001254proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255{
1256 char proc[32];
1257 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001258#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001259 int i;
1260 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 sigset_t signals;
1262 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264#ifndef HAVE_POLLABLE_PROCFS
1265 static int last_pfd;
1266#endif
1267
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001268#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001269 /* Open the process pseudo-files in /proc. */
1270 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1271 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272 perror("strace: open(\"/proc/...\", ...)");
1273 return -1;
1274 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001275 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001276 sprintf(proc, "/proc/%d/status", tcp->pid);
1277 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1278 perror("strace: open(\"/proc/...\", ...)");
1279 return -1;
1280 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001281 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001282 sprintf(proc, "/proc/%d/as", tcp->pid);
1283 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1284 perror("strace: open(\"/proc/...\", ...)");
1285 return -1;
1286 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001287 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001288#else
1289 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001290#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001291 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001292 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001293#else /* FREEBSD */
1294 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001295 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001296#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001297 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001298 perror("strace: open(\"/proc/...\", ...)");
1299 return -1;
1300 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001301 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001302#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001303#ifdef FREEBSD
1304 sprintf(proc, "/proc/%d/regs", tcp->pid);
1305 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1306 perror("strace: open(\"/proc/.../regs\", ...)");
1307 return -1;
1308 }
1309 if (cflag) {
1310 sprintf(proc, "/proc/%d/status", tcp->pid);
1311 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1312 perror("strace: open(\"/proc/.../status\", ...)");
1313 return -1;
1314 }
1315 } else
1316 tcp->pfd_status = -1;
1317#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001318 rebuild_pollv();
1319 if (!attaching) {
1320 /*
1321 * Wait for the child to pause. Because of a race
1322 * condition we have to poll for the event.
1323 */
1324 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001325 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001326 perror("strace: PIOCSTATUS");
1327 return -1;
1328 }
1329 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001330 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001331 }
1332 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001333#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001334 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001335 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001336 perror("strace: PIOCSTOP");
1337 return -1;
1338 }
Roland McGrath553a6092002-12-16 20:40:39 +00001339#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340#ifdef PIOCSET
1341 /* Set Run-on-Last-Close. */
1342 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001343 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344 perror("PIOCSET PR_RLC");
1345 return -1;
1346 }
1347 /* Set or Reset Inherit-on-Fork. */
1348 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001349 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350 perror("PIOC{SET,RESET} PR_FORK");
1351 return -1;
1352 }
1353#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001354#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001355 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1356 perror("PIOCSRLC");
1357 return -1;
1358 }
1359 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1360 perror("PIOC{S,R}FORK");
1361 return -1;
1362 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001363#else /* FREEBSD */
1364 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1365 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1366 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001367 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001368 }
1369 arg &= ~PF_LINGER;
1370 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001371 perror("PIOCSFL");
1372 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001373 }
1374#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001376#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001377 /* Enable all syscall entries we care about. */
1378 premptyset(&syscalls);
1379 for (i = 1; i < MAX_QUALS; ++i) {
1380 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001381 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001382 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001383 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001384 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001385 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001386#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001387 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001388#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001389#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001390 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001391#endif
1392#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001393 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001394#endif
1395#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001396 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001397#endif
1398 }
1399 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001400 perror("PIOCSENTRY");
1401 return -1;
1402 }
John Hughes19e49982001-10-19 08:59:12 +00001403 /* Enable the syscall exits. */
1404 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405 perror("PIOSEXIT");
1406 return -1;
1407 }
John Hughes19e49982001-10-19 08:59:12 +00001408 /* Enable signals we care about. */
1409 premptyset(&signals);
1410 for (i = 1; i < MAX_QUALS; ++i) {
1411 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001412 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001413 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001414 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 perror("PIOCSTRACE");
1416 return -1;
1417 }
John Hughes19e49982001-10-19 08:59:12 +00001418 /* Enable faults we care about */
1419 premptyset(&faults);
1420 for (i = 1; i < MAX_QUALS; ++i) {
1421 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001422 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001423 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001424 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425 perror("PIOCSFAULT");
1426 return -1;
1427 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001428#else /* FREEBSD */
1429 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001430 arg = S_SIG | S_SCE | S_SCX;
1431 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001432 perror("PIOCBIS");
1433 return -1;
1434 }
1435#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 if (!attaching) {
1437#ifdef MIPS
1438 /*
1439 * The SGI PRSABORT doesn't work for pause() so
1440 * we send it a caught signal to wake it up.
1441 */
1442 kill(tcp->pid, SIGINT);
1443#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001444#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001446 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001447 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448 perror("PIOCRUN");
1449 return -1;
1450 }
Roland McGrath553a6092002-12-16 20:40:39 +00001451#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001452#endif /* !MIPS*/
1453#ifdef FREEBSD
1454 /* wake up the child if it received the SIGSTOP */
1455 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001456#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457 for (;;) {
1458 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001459 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 perror("PIOCWSTOP");
1461 return -1;
1462 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001463 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001464 tcp->flags &= ~TCB_INSYSCALL;
1465 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001466 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467 break;
1468 }
1469 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001470#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001471 arg = 0;
1472 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001473#else /* FREEBSD */
1474 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001475#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 perror("PIOCRUN");
1477 return -1;
1478 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001479#ifdef FREEBSD
1480 /* handle the case where we "opened" the child before
1481 it did the kill -STOP */
1482 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1483 tcp->status.PR_WHAT == SIGSTOP)
1484 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001485#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001486 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001487#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001489#else /* FREEBSD */
1490 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001491 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001492 /* We are attaching to an already running process.
1493 * Try to figure out the state of the process in syscalls,
1494 * to handle the first event well.
1495 * This is done by having a look at the "wchan" property of the
1496 * process, which tells where it is stopped (if it is). */
1497 FILE * status;
1498 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001499
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001500 sprintf(proc, "/proc/%d/status", tcp->pid);
1501 status = fopen(proc, "r");
1502 if (status &&
1503 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1504 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1505 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1506 strcmp(wchan, "stopevent")) {
1507 /* The process is asleep in the middle of a syscall.
1508 Fake the syscall entry event */
1509 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1510 tcp->status.PR_WHY = PR_SYSENTRY;
1511 trace_syscall(tcp);
1512 }
1513 if (status)
1514 fclose(status);
1515 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001516 }
1517#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518#ifndef HAVE_POLLABLE_PROCFS
1519 if (proc_poll_pipe[0] != -1)
1520 proc_poller(tcp->pfd);
1521 else if (nprocs > 1) {
1522 proc_poll_open();
1523 proc_poller(last_pfd);
1524 proc_poller(tcp->pfd);
1525 }
1526 last_pfd = tcp->pfd;
1527#endif /* !HAVE_POLLABLE_PROCFS */
1528 return 0;
1529}
1530
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001531#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001533struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001534pid2tcb(int pid)
1535{
1536 int i;
1537
1538 if (pid <= 0)
1539 return NULL;
1540
1541 for (i = 0; i < tcbtabsize; i++) {
1542 struct tcb *tcp = tcbtab[i];
1543 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1544 return tcp;
1545 }
1546
1547 return NULL;
1548}
1549
1550#ifdef USE_PROCFS
1551
1552static struct tcb *
1553first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554{
1555 int i;
1556 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001557 for (i = 0; i < tcbtabsize; i++) {
1558 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559 if (tcp->flags & TCB_INUSE)
1560 return tcp;
1561 }
1562 return NULL;
1563}
1564
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001566pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567{
1568 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569
Roland McGrathca16be82003-01-10 19:55:28 +00001570 for (i = 0; i < tcbtabsize; i++) {
1571 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 if (tcp->pfd != pfd)
1573 continue;
1574 if (tcp->flags & TCB_INUSE)
1575 return tcp;
1576 }
1577 return NULL;
1578}
1579
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001580#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581
1582void
Denys Vlasenko12014262011-05-30 14:00:14 +02001583droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584{
1585 if (tcp->pid == 0)
1586 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001587#ifdef TCB_CLONE_THREAD
1588 if (tcp->nclone_threads > 0) {
1589 /* There are other threads left in this process, but this
1590 is the one whose PID represents the whole process.
1591 We need to keep this record around as a zombie until
1592 all the threads die. */
1593 tcp->flags |= TCB_EXITING;
1594 return;
1595 }
1596#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 nprocs--;
1598 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001599
Roland McGrathe29341c2003-01-10 20:14:20 +00001600 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001601#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001602 if (tcp->flags & TCB_CLONE_THREAD)
1603 tcp->parent->nclone_threads--;
1604#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001605#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001606 /* Update fields like NCLONE_DETACHED, only
1607 for zombie group leader that has already reported
1608 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001609 function. The same condition as at the top of DETACH. */
1610 if ((tcp->flags & TCB_CLONE_THREAD) &&
1611 tcp->parent->nclone_threads == 0 &&
1612 (tcp->parent->flags & TCB_EXITING))
1613 droptcb(tcp->parent);
1614#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001615 tcp->parent = NULL;
1616 }
1617
1618 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619 if (tcp->pfd != -1) {
1620 close(tcp->pfd);
1621 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001622#ifdef FREEBSD
1623 if (tcp->pfd_reg != -1) {
1624 close(tcp->pfd_reg);
1625 tcp->pfd_reg = -1;
1626 }
1627 if (tcp->pfd_status != -1) {
1628 close(tcp->pfd_status);
1629 tcp->pfd_status = -1;
1630 }
Roland McGrath553a6092002-12-16 20:40:39 +00001631#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001632#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001633 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634#endif
1635 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001636
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001637 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001639
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640 tcp->outf = 0;
1641}
1642
Roland McGrath0a463882007-07-05 18:43:16 +00001643/* detach traced process; continue with sig
1644 Never call DETACH twice on the same process as both unattached and
1645 attached-unstopped processes give the same ESRCH. For unattached process we
1646 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647
1648static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001649detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650{
1651 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001652#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001653 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001654 struct tcb *zombie = NULL;
1655
1656 /* If the group leader is lingering only because of this other
1657 thread now dying, then detach the leader as well. */
1658 if ((tcp->flags & TCB_CLONE_THREAD) &&
1659 tcp->parent->nclone_threads == 1 &&
1660 (tcp->parent->flags & TCB_EXITING))
1661 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001662#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663
1664 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001665 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666
1667#ifdef LINUX
1668 /*
1669 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001670 * before detaching. Arghh. We go through hoops
1671 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001673#if defined(SPARC)
1674#undef PTRACE_DETACH
1675#define PTRACE_DETACH PTRACE_SUNDETACH
1676#endif
Roland McGrath02203312007-06-11 22:06:31 +00001677 /*
1678 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1679 * expected SIGSTOP. We must catch exactly one as otherwise the
1680 * detached process would be left stopped (process state T).
1681 */
1682 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1684 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001685 }
1686 else if (errno != ESRCH) {
1687 /* Shouldn't happen. */
1688 perror("detach: ptrace(PTRACE_DETACH, ...)");
1689 }
Roland McGrath134813a2007-06-02 00:07:33 +00001690 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1691 : tcp->pid),
1692 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001693 if (errno != ESRCH)
1694 perror("detach: checking sanity");
1695 }
Roland McGrath02203312007-06-11 22:06:31 +00001696 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1697 ? tcp->parent->pid : tcp->pid),
1698 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001699 if (errno != ESRCH)
1700 perror("detach: stopping child");
1701 }
Roland McGrath02203312007-06-11 22:06:31 +00001702 else
1703 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001704 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001706#ifdef __WALL
1707 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1708 if (errno == ECHILD) /* Already gone. */
1709 break;
1710 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001711 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001712 break;
1713 }
1714#endif /* __WALL */
1715 /* No __WALL here. */
1716 if (waitpid(tcp->pid, &status, 0) < 0) {
1717 if (errno != ECHILD) {
1718 perror("detach: waiting");
1719 break;
1720 }
1721#ifdef __WCLONE
1722 /* If no processes, try clones. */
1723 if (wait4(tcp->pid, &status, __WCLONE,
1724 NULL) < 0) {
1725 if (errno != ECHILD)
1726 perror("detach: waiting");
1727 break;
1728 }
1729#endif /* __WCLONE */
1730 }
1731#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001732 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001733#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 if (!WIFSTOPPED(status)) {
1735 /* Au revoir, mon ami. */
1736 break;
1737 }
1738 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001739 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001740 break;
1741 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001742 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001743 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001744 : WSTOPSIG(status));
1745 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001747 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001748 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001749#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750
1751#if defined(SUNOS4)
1752 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1753 if (sig && kill(tcp->pid, sig) < 0)
1754 perror("detach: kill");
1755 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001756 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757#endif /* SUNOS4 */
1758
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759 if (!qflag)
1760 fprintf(stderr, "Process %u detached\n", tcp->pid);
1761
1762 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001763
1764#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001765 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001766 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001767 droptcb(zombie);
1768 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001769#endif
1770
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771 return error;
1772}
1773
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001774#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001776static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777{
1778 int pid;
1779 int status;
1780
1781 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782 }
1783}
1784
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001785#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786
1787static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001788cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789{
1790 int i;
1791 struct tcb *tcp;
1792
Roland McGrathee9d4352002-12-18 04:16:10 +00001793 for (i = 0; i < tcbtabsize; i++) {
1794 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 if (!(tcp->flags & TCB_INUSE))
1796 continue;
1797 if (debug)
1798 fprintf(stderr,
1799 "cleanup: looking at pid %u\n", tcp->pid);
1800 if (tcp_last &&
1801 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001802 tprintf(" <unfinished ...>");
1803 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 }
1805 if (tcp->flags & TCB_ATTACHED)
1806 detach(tcp, 0);
1807 else {
1808 kill(tcp->pid, SIGCONT);
1809 kill(tcp->pid, SIGTERM);
1810 }
1811 }
1812 if (cflag)
1813 call_summary(outf);
1814}
1815
1816static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001817interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818{
1819 interrupted = 1;
1820}
1821
1822#ifndef HAVE_STRERROR
1823
Roland McGrath6d2b3492002-12-30 00:51:30 +00001824#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825extern int sys_nerr;
1826extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001827#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828
1829const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001830strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001831{
1832 static char buf[64];
1833
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001834 if (err_no < 1 || err_no >= sys_nerr) {
1835 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836 return buf;
1837 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001838 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839}
1840
1841#endif /* HAVE_STERRROR */
1842
1843#ifndef HAVE_STRSIGNAL
1844
Roland McGrath8f474e02003-01-14 07:53:33 +00001845#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001846extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001848#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1849extern char *_sys_siglist[];
1850#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851
1852const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001853strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001854{
1855 static char buf[64];
1856
1857 if (sig < 1 || sig >= NSIG) {
1858 sprintf(buf, "Unknown signal %d", sig);
1859 return buf;
1860 }
1861#ifdef HAVE__SYS_SIGLIST
1862 return _sys_siglist[sig];
1863#else
1864 return sys_siglist[sig];
1865#endif
1866}
1867
1868#endif /* HAVE_STRSIGNAL */
1869
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001870#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871
1872static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001873rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874{
1875 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876
Roland McGrathee9d4352002-12-18 04:16:10 +00001877 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001878 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001879 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001880 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001881 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001882 exit(1);
1883 }
1884
Roland McGrathca16be82003-01-10 19:55:28 +00001885 for (i = j = 0; i < tcbtabsize; i++) {
1886 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887 if (!(tcp->flags & TCB_INUSE))
1888 continue;
1889 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001890 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001891 j++;
1892 }
1893 if (j != nprocs) {
1894 fprintf(stderr, "strace: proc miscount\n");
1895 exit(1);
1896 }
1897}
1898
1899#ifndef HAVE_POLLABLE_PROCFS
1900
1901static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001902proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904 int i;
1905
1906 if (pipe(proc_poll_pipe) < 0) {
1907 perror("pipe");
1908 exit(1);
1909 }
1910 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001911 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912 }
1913}
1914
1915static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001916proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917{
1918 int i;
1919 int n;
1920 struct proc_pollfd pollinfo;
1921
1922 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1923 return n;
1924 if (n != sizeof(struct proc_pollfd)) {
1925 fprintf(stderr, "panic: short read: %d\n", n);
1926 exit(1);
1927 }
1928 for (i = 0; i < nprocs; i++) {
1929 if (pollv[i].fd == pollinfo.fd)
1930 pollv[i].revents = pollinfo.revents;
1931 else
1932 pollv[i].revents = 0;
1933 }
1934 poller_pid = pollinfo.pid;
1935 return 1;
1936}
1937
1938static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001939wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940{
1941}
1942
1943static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001944proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945{
1946 struct proc_pollfd pollinfo;
1947 struct sigaction sa;
1948 sigset_t blocked_set, empty_set;
1949 int i;
1950 int n;
1951 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001952#ifdef FREEBSD
1953 struct procfs_status pfs;
1954#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955
1956 switch (fork()) {
1957 case -1:
1958 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001959 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960 case 0:
1961 break;
1962 default:
1963 return;
1964 }
1965
1966 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1967 sa.sa_flags = 0;
1968 sigemptyset(&sa.sa_mask);
1969 sigaction(SIGHUP, &sa, NULL);
1970 sigaction(SIGINT, &sa, NULL);
1971 sigaction(SIGQUIT, &sa, NULL);
1972 sigaction(SIGPIPE, &sa, NULL);
1973 sigaction(SIGTERM, &sa, NULL);
1974 sa.sa_handler = wakeup_handler;
1975 sigaction(SIGUSR1, &sa, NULL);
1976 sigemptyset(&blocked_set);
1977 sigaddset(&blocked_set, SIGUSR1);
1978 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1979 sigemptyset(&empty_set);
1980
1981 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1982 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001983 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984 }
1985 n = rl.rlim_cur;
1986 for (i = 0; i < n; i++) {
1987 if (i != pfd && i != proc_poll_pipe[1])
1988 close(i);
1989 }
1990
1991 pollinfo.fd = pfd;
1992 pollinfo.pid = getpid();
1993 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001994#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001995 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1996#else
1997 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1998#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001999 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 switch (errno) {
2001 case EINTR:
2002 continue;
2003 case EBADF:
2004 pollinfo.revents = POLLERR;
2005 break;
2006 case ENOENT:
2007 pollinfo.revents = POLLHUP;
2008 break;
2009 default:
2010 perror("proc_poller: PIOCWSTOP");
2011 }
2012 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2013 _exit(0);
2014 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002015 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2017 sigsuspend(&empty_set);
2018 }
2019}
2020
2021#endif /* !HAVE_POLLABLE_PROCFS */
2022
2023static int
2024choose_pfd()
2025{
2026 int i, j;
2027 struct tcb *tcp;
2028
2029 static int last;
2030
2031 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002032 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033 /*
2034 * The previous process is ready to run again. We'll
2035 * let it do so if it is currently in a syscall. This
2036 * heuristic improves the readability of the trace.
2037 */
2038 tcp = pfd2tcb(pollv[last].fd);
2039 if (tcp && (tcp->flags & TCB_INSYSCALL))
2040 return pollv[last].fd;
2041 }
2042
2043 for (i = 0; i < nprocs; i++) {
2044 /* Let competing children run round robin. */
2045 j = (i + last + 1) % nprocs;
2046 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2047 tcp = pfd2tcb(pollv[j].fd);
2048 if (!tcp) {
2049 fprintf(stderr, "strace: lost proc\n");
2050 exit(1);
2051 }
2052 droptcb(tcp);
2053 return -1;
2054 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002055 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 last = j;
2057 return pollv[j].fd;
2058 }
2059 }
2060 fprintf(stderr, "strace: nothing ready\n");
2061 exit(1);
2062}
2063
2064static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002065trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002066{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002067#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002068 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002069#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 struct tcb *tcp;
2071 int pfd;
2072 int what;
2073 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002074 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002075
2076 for (;;) {
2077 if (interactive)
2078 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2079
2080 if (nprocs == 0)
2081 break;
2082
2083 switch (nprocs) {
2084 case 1:
2085#ifndef HAVE_POLLABLE_PROCFS
2086 if (proc_poll_pipe[0] == -1) {
2087#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002088 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002089 if (!tcp)
2090 continue;
2091 pfd = tcp->pfd;
2092 if (pfd == -1)
2093 continue;
2094 break;
2095#ifndef HAVE_POLLABLE_PROCFS
2096 }
2097 /* fall through ... */
2098#endif /* !HAVE_POLLABLE_PROCFS */
2099 default:
2100#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002101#ifdef POLL_HACK
2102 /* On some systems (e.g. UnixWare) we get too much ugly
2103 "unfinished..." stuff when multiple proceses are in
2104 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002105
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002106 if (in_syscall) {
2107 struct pollfd pv;
2108 tcp = in_syscall;
2109 in_syscall = NULL;
2110 pv.fd = tcp->pfd;
2111 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002112 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002113 if (interrupted)
2114 return 0;
2115 continue;
2116 }
2117 else if (what == 1 && pv.revents & POLLWANT) {
2118 goto FOUND;
2119 }
2120 }
2121#endif
2122
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002123 if (poll(pollv, nprocs, INFTIM) < 0) {
2124 if (interrupted)
2125 return 0;
2126 continue;
2127 }
2128#else /* !HAVE_POLLABLE_PROCFS */
2129 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2130 if (interrupted)
2131 return 0;
2132 continue;
2133 }
2134#endif /* !HAVE_POLLABLE_PROCFS */
2135 pfd = choose_pfd();
2136 if (pfd == -1)
2137 continue;
2138 break;
2139 }
2140
2141 /* Look up `pfd' in our table. */
2142 if ((tcp = pfd2tcb(pfd)) == NULL) {
2143 fprintf(stderr, "unknown pfd: %u\n", pfd);
2144 exit(1);
2145 }
John Hughesb6643082002-05-23 11:02:22 +00002146#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002147 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002148#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 /* Get the status of the process. */
2150 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002151#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002152 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002153#else /* FREEBSD */
2154 /* Thanks to some scheduling mystery, the first poller
2155 sometimes waits for the already processed end of fork
2156 event. Doing a non blocking poll here solves the problem. */
2157 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002158 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002159 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002160 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002161#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002162 ioctl_errno = errno;
2163#ifndef HAVE_POLLABLE_PROCFS
2164 if (proc_poll_pipe[0] != -1) {
2165 if (ioctl_result < 0)
2166 kill(poller_pid, SIGKILL);
2167 else
2168 kill(poller_pid, SIGUSR1);
2169 }
2170#endif /* !HAVE_POLLABLE_PROCFS */
2171 }
2172 if (interrupted)
2173 return 0;
2174
2175 if (interactive)
2176 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2177
2178 if (ioctl_result < 0) {
2179 /* Find out what happened if it failed. */
2180 switch (ioctl_errno) {
2181 case EINTR:
2182 case EBADF:
2183 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002184#ifdef FREEBSD
2185 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002186#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 case ENOENT:
2188 droptcb(tcp);
2189 continue;
2190 default:
2191 perror("PIOCWSTOP");
2192 exit(1);
2193 }
2194 }
2195
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002196#ifdef FREEBSD
2197 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2198 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002199 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002200 continue;
2201 }
Roland McGrath553a6092002-12-16 20:40:39 +00002202#endif
2203
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204 /* clear the just started flag */
2205 tcp->flags &= ~TCB_STARTUP;
2206
2207 /* set current output file */
2208 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002209 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002210
2211 if (cflag) {
2212 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002213#ifdef FREEBSD
2214 char buf[1024];
2215 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002216
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002217 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2218 buf[len] = '\0';
2219 sscanf(buf,
2220 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2221 &stime.tv_sec, &stime.tv_usec);
2222 } else
2223 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002224#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2226 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002227#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002228 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2229 tcp->stime = stime;
2230 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002231 what = tcp->status.PR_WHAT;
2232 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002233#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002235 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2236 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237 if (trace_syscall(tcp) < 0) {
2238 fprintf(stderr, "syscall trouble\n");
2239 exit(1);
2240 }
2241 }
2242 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002243#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002245#ifdef POLL_HACK
2246 in_syscall = tcp;
2247#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248 case PR_SYSEXIT:
2249 if (trace_syscall(tcp) < 0) {
2250 fprintf(stderr, "syscall trouble\n");
2251 exit(1);
2252 }
2253 break;
2254 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002255 if (cflag != CFLAG_ONLY_STATS
2256 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 printleader(tcp);
2258 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002259 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002260 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002261#ifdef PR_INFO
2262 if (tcp->status.PR_INFO.si_signo == what) {
2263 printleader(tcp);
2264 tprintf(" siginfo=");
2265 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002266 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002267 }
2268#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002269 }
2270 break;
2271 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002272 if (cflag != CFLAGS_ONLY_STATS
2273 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274 printleader(tcp);
2275 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002276 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277 }
2278 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002279#ifdef FREEBSD
2280 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002281 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002282#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002284 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285 exit(1);
2286 break;
2287 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002288 /* Remember current print column before continuing. */
2289 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002290 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002291#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002292 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002293#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002294 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002295#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002296 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002297 perror("PIOCRUN");
2298 exit(1);
2299 }
2300 }
2301 return 0;
2302}
2303
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002304#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002306#ifdef TCB_GROUP_EXITING
2307/* Handle an exit detach or death signal that is taking all the
2308 related clone threads with it. This is called in three circumstances:
2309 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2310 SIG == 0 Continuing TCP will perform an exit_group syscall.
2311 SIG == other Continuing TCP with SIG will kill the process.
2312*/
2313static int
2314handle_group_exit(struct tcb *tcp, int sig)
2315{
2316 /* We need to locate our records of all the clone threads
2317 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002318 struct tcb *leader = NULL;
2319
2320 if (tcp->flags & TCB_CLONE_THREAD)
2321 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002322
2323 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002324 if (leader != NULL && leader != tcp
2325 && !(leader->flags & TCB_GROUP_EXITING)
2326 && !(tcp->flags & TCB_STARTUP)
2327 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002328 fprintf(stderr,
2329 "PANIC: handle_group_exit: %d leader %d\n",
2330 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002331 }
2332 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002333 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002334 }
2335 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002336 /* Mark that we are taking the process down. */
2337 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002338 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002339 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002340 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002341 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002342 } else {
2343 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2344 cleanup();
2345 return -1;
2346 }
2347 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002348 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002349 if (leader != tcp)
2350 droptcb(tcp);
2351 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002352 /* The leader will report to us as parent now,
2353 and then we'll get to the SIG==-1 case. */
2354 return 0;
2355 }
2356 }
2357
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002358 return 0;
2359}
2360#endif
2361
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002362#ifdef LINUX
2363static int
2364handle_ptrace_event(int status, struct tcb *tcp)
2365{
2366 if (status >> 16 == PTRACE_EVENT_VFORK ||
2367 status >> 16 == PTRACE_EVENT_CLONE ||
2368 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002369 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002370
2371 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2372 if (errno != ESRCH) {
2373 fprintf(stderr, "\
2374%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2375 progname);
2376 cleanup();
2377 exit(1);
2378 }
2379 return -1;
2380 }
2381 return handle_new_child(tcp, childpid, 0);
2382 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002383 if (status >> 16 == PTRACE_EVENT_EXEC) {
2384 if (debug)
2385 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2386 return 0;
2387 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002388 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2389 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002390 return 1;
2391}
2392#endif
2393
Roland McGratheb9e2e82009-06-02 16:49:22 -07002394static int
2395trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396{
2397 int pid;
2398 int wait_errno;
2399 int status;
2400 struct tcb *tcp;
2401#ifdef LINUX
2402 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002403#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002404 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002405#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002406#endif /* LINUX */
2407
Roland McGratheb9e2e82009-06-02 16:49:22 -07002408 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002409 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002410 return 0;
2411 if (interactive)
2412 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002413#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002414#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002415 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002416 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002417 /* this kernel does not support __WALL */
2418 wait4_options &= ~__WALL;
2419 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002420 pid = wait4(-1, &status, wait4_options,
2421 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002422 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002423 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002424 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002425 pid = wait4(-1, &status, __WCLONE,
2426 cflag ? &ru : NULL);
2427 if (pid == -1) {
2428 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002429 "failed: %s\n", strerror(errno));
2430 }
2431 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002432#else
2433 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2434#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002435#endif /* LINUX */
2436#ifdef SUNOS4
2437 pid = wait(&status);
2438#endif /* SUNOS4 */
2439 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002440 if (interactive)
2441 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002444 switch (wait_errno) {
2445 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002446 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002447 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002448 /*
2449 * We would like to verify this case
2450 * but sometimes a race in Solbourne's
2451 * version of SunOS sometimes reports
2452 * ECHILD before sending us SIGCHILD.
2453 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002454 return 0;
2455 default:
2456 errno = wait_errno;
2457 perror("strace: wait");
2458 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002459 }
2460 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002461 if (pid == popen_pid) {
2462 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002463 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002464 continue;
2465 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002466 if (debug)
2467 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2468
2469 /* Look up `pid' in our table. */
2470 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002471#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002472 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002473 /* This is needed to go with the CLONE_PTRACE
2474 changes in process.c/util.c: we might see
2475 the child's initial trap before we see the
2476 parent return from the clone syscall.
2477 Leave the child suspended until the parent
2478 returns from its system call. Only then
2479 will we have the association of parent and
2480 child so that we know how to do clearbpt
2481 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002482 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002483 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002484 if (!qflag)
2485 fprintf(stderr, "\
2486Process %d attached (waiting for parent)\n",
2487 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002488 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002489 else
2490 /* This can happen if a clone call used
2491 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002492#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002493 {
2494 fprintf(stderr, "unknown pid: %u\n", pid);
2495 if (WIFSTOPPED(status))
2496 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2497 exit(1);
2498 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002500 /* set current output file */
2501 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002502 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002503 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002504#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002505 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2506 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002507#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002508 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002509
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510 if (tcp->flags & TCB_SUSPENDED) {
2511 /*
2512 * Apparently, doing any ptrace() call on a stopped
2513 * process, provokes the kernel to report the process
2514 * status again on a subsequent wait(), even if the
2515 * process has not been actually restarted.
2516 * Since we have inspected the arguments of suspended
2517 * processes we end up here testing for this case.
2518 */
2519 continue;
2520 }
2521 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002522 if (pid == strace_child)
2523 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002524 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2526 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002527 tprintf("+++ killed by %s %s+++",
2528 signame(WTERMSIG(status)),
2529#ifdef WCOREDUMP
2530 WCOREDUMP(status) ? "(core dumped) " :
2531#endif
2532 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002533 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002534 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002535#ifdef TCB_GROUP_EXITING
2536 handle_group_exit(tcp, -1);
2537#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002538 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002539#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 continue;
2541 }
2542 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002543 if (pid == strace_child)
2544 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002545 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002546 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2547 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002548#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002549 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002550 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002551#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002552 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002554 "PANIC: attached pid %u exited with %d\n",
2555 pid, WEXITSTATUS(status));
2556 }
Roland McGrath0a396902003-06-10 03:05:53 +00002557 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002558 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002559 tprintf(" <unfinished ... exit status %d>\n",
2560 WEXITSTATUS(status));
2561 tcp_last = NULL;
2562 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002563#ifdef TCB_GROUP_EXITING
2564 handle_group_exit(tcp, -1);
2565#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002566 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002567#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568 continue;
2569 }
2570 if (!WIFSTOPPED(status)) {
2571 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2572 droptcb(tcp);
2573 continue;
2574 }
2575 if (debug)
2576 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002577 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002578
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002579 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002580 if (handle_ptrace_event(status, tcp) != 1)
2581 goto tracing;
2582 }
2583
Roland McGrath02203312007-06-11 22:06:31 +00002584 /*
2585 * Interestingly, the process may stop
2586 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002587 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002588 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002589 * A no-MMU vforked child won't send up a signal,
2590 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002591 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002592 if ((tcp->flags & TCB_STARTUP) &&
2593 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002594 /*
2595 * This flag is there to keep us in sync.
2596 * Next time this process stops it should
2597 * really be entering a system call.
2598 */
2599 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002600 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002601 /*
2602 * One example is a breakpoint inherited from
2603 * parent through fork ().
2604 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2606 droptcb(tcp);
2607 cleanup();
2608 return -1;
2609 }
2610 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002611#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002612 /* If options were not set for this tracee yet */
2613 if (tcp->parent == NULL) {
2614 if (ptrace_setoptions) {
2615 if (debug)
2616 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2617 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2618 if (errno != ESRCH) {
2619 /* Should never happen, really */
2620 perror_msg_and_die("PTRACE_SETOPTIONS");
2621 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002622 }
2623 }
2624 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002625#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002626 goto tracing;
2627 }
2628
Denys Vlasenko75422762011-05-27 14:36:01 +02002629 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002630 if (WSTOPSIG(status) == SIGSTOP &&
2631 (tcp->flags & TCB_SIGTRAPPED)) {
2632 /*
2633 * Trapped attempt to block SIGTRAP
2634 * Hope we are back in control now.
2635 */
2636 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002637 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002638 cleanup();
2639 return -1;
2640 }
2641 continue;
2642 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002643 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002644 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002645 siginfo_t si;
2646#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002647 long pc = 0;
2648 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002649
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002650 upeek(tcp, PT_CR_IPSR, &psr);
2651 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002652
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002653# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002654 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002655# define PC_FORMAT_STR " @ %lx"
2656# define PC_FORMAT_ARG pc
2657#else
2658# define PC_FORMAT_STR "%s"
2659# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002660#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002662 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2663 tprintf("--- ");
2664 printsiginfo(&si, verbose(tcp));
2665 tprintf(" (%s)" PC_FORMAT_STR " ---",
2666 strsignal(WSTOPSIG(status)),
2667 PC_FORMAT_ARG);
2668 } else
2669 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2670 strsignal(WSTOPSIG(status)),
2671 signame(WSTOPSIG(status)),
2672 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002673 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002674 }
Roland McGrath05690952004-10-20 01:00:27 +00002675 if (((tcp->flags & TCB_ATTACHED) ||
2676 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002677 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002678#ifdef TCB_GROUP_EXITING
2679 handle_group_exit(tcp, WSTOPSIG(status));
2680#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002681 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002682#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002683 continue;
2684 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002685 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002686 cleanup();
2687 return -1;
2688 }
2689 tcp->flags &= ~TCB_SUSPENDED;
2690 continue;
2691 }
Roland McGrath02203312007-06-11 22:06:31 +00002692 /* we handled the STATUS, we are permitted to interrupt now. */
2693 if (interrupted)
2694 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002695 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2696 /* ptrace() failed in trace_syscall() with ESRCH.
2697 * Likely a result of process disappearing mid-flight.
2698 * Observed case: exit_group() terminating
2699 * all processes in thread group. In this case, threads
2700 * "disappear" in an unpredictable moment without any
2701 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002702 */
2703 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002704 if (tcp_last) {
2705 /* Do we have dangling line "syscall(param, param"?
2706 * Finish the line then. We cannot
2707 */
2708 tcp_last->flags |= TCB_REPRINT;
2709 tprintf(" <unfinished ...>");
2710 printtrailer();
2711 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002712 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002713 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002714 ptrace(PTRACE_KILL,
2715 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002716 droptcb(tcp);
2717 }
2718 continue;
2719 }
2720 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002721#ifdef TCB_GROUP_EXITING
2722 if (tcp->flags & TCB_GROUP_EXITING) {
2723 if (handle_group_exit(tcp, 0) < 0)
2724 return -1;
2725 continue;
2726 }
2727#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002728 if (tcp->flags & TCB_ATTACHED)
2729 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002730 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002731 cleanup();
2732 return -1;
2733 }
2734 continue;
2735 }
2736 if (tcp->flags & TCB_SUSPENDED) {
2737 if (!qflag)
2738 fprintf(stderr, "Process %u suspended\n", pid);
2739 continue;
2740 }
2741 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002742 /* Remember current print column before continuing. */
2743 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002744 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002745 cleanup();
2746 return -1;
2747 }
2748 }
2749 return 0;
2750}
2751
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002752#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002753
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002754#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002755
2756void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002757tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002758{
2759 va_list args;
2760
Andreas Schwabe5355de2009-10-27 16:56:43 +01002761 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002762 if (outf) {
2763 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002764 if (n < 0) {
2765 if (outf != stderr)
2766 perror(outfname == NULL
2767 ? "<writing to pipe>" : outfname);
2768 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002769 curcol += n;
2770 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002771 va_end(args);
2772 return;
2773}
2774
2775void
Denys Vlasenko12014262011-05-30 14:00:14 +02002776printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002777{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002778 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002779 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002780 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002781 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002782 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002783 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002784 tprintf("= ? <unavailable>\n");
2785 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002786 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002787 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002788 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002789 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002790 }
2791 curcol = 0;
2792 if ((followfork == 1 || pflag_seen > 1) && outfname)
2793 tprintf("%-5d ", tcp->pid);
2794 else if (nprocs > 1 && !outfname)
2795 tprintf("[pid %5u] ", tcp->pid);
2796 if (tflag) {
2797 char str[sizeof("HH:MM:SS")];
2798 struct timeval tv, dtv;
2799 static struct timeval otv;
2800
2801 gettimeofday(&tv, NULL);
2802 if (rflag) {
2803 if (otv.tv_sec == 0)
2804 otv = tv;
2805 tv_sub(&dtv, &tv, &otv);
2806 tprintf("%6ld.%06ld ",
2807 (long) dtv.tv_sec, (long) dtv.tv_usec);
2808 otv = tv;
2809 }
2810 else if (tflag > 2) {
2811 tprintf("%ld.%06ld ",
2812 (long) tv.tv_sec, (long) tv.tv_usec);
2813 }
2814 else {
2815 time_t local = tv.tv_sec;
2816 strftime(str, sizeof(str), "%T", localtime(&local));
2817 if (tflag > 1)
2818 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2819 else
2820 tprintf("%s ", str);
2821 }
2822 }
2823 if (iflag)
2824 printcall(tcp);
2825}
2826
2827void
Denys Vlasenko12014262011-05-30 14:00:14 +02002828tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002829{
2830 if (curcol < col)
2831 tprintf("%*s", col - curcol, "");
2832}
2833
2834void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002835printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002836{
2837 tprintf("\n");
2838 tcp_last = NULL;
2839}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002840
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002841#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002842
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002843int
2844mp_ioctl(int fd, int cmd, void *arg, int size)
2845{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002846 struct iovec iov[2];
2847 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002848
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002849 iov[0].iov_base = &cmd;
2850 iov[0].iov_len = sizeof cmd;
2851 if (arg) {
2852 ++n;
2853 iov[1].iov_base = arg;
2854 iov[1].iov_len = size;
2855 }
Roland McGrath553a6092002-12-16 20:40:39 +00002856
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002857 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002858}
2859
2860#endif