blob: 470bc089019c33c0acf65675a95496753541bdb6 [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
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200320 if (euid != uid && setreuid(euid, uid) < 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000321 fprintf(stderr, "%s: setreuid: %s\n",
322 progname, strerror(errno));
323 exit(1);
324 }
325#endif
326}
327
Roland McGrath4bfa6262007-07-05 20:03:16 +0000328#if _LFS64_LARGEFILE
329# define fopen_for_output fopen64
330#else
331# define fopen_for_output fopen
332#endif
333
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000334static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200335strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000336{
337 FILE *fp;
338
339 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200340 fp = fopen_for_output(path, "w");
341 if (!fp)
342 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200344 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000345 return fp;
346}
347
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200348static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000349
350#ifndef _PATH_BSHELL
351# define _PATH_BSHELL "/bin/sh"
352#endif
353
354/*
355 * We cannot use standard popen(3) here because we have to distinguish
356 * popen child process from other processes we trace, and standard popen(3)
357 * does not export its child's pid.
358 */
359static FILE *
360strace_popen(const char *command)
361{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200362 FILE *fp;
363 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364
365 swap_uid();
366 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200367 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000368
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200369 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200371 popen_pid = vfork();
372 if (popen_pid == -1)
373 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000374
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200375 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376 /* child */
377 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200378 if (fds[0] != 0) {
379 if (dup2(fds[0], 0))
380 perror_msg_and_die("dup2");
381 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000382 }
383 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200384 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000385 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200386
387 /* parent */
388 close(fds[0]);
389 swap_uid();
390 fp = fdopen(fds[1], "w");
391 if (!fp)
392 error_msg_and_die("Out of memory");
393 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000394}
395
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200396static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397newoutf(struct tcb *tcp)
398{
399 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000400 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000401 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200402 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000403 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000404}
405
Roland McGrath02203312007-06-11 22:06:31 +0000406static void
407startup_attach(void)
408{
409 int tcbi;
410 struct tcb *tcp;
411
412 /*
413 * Block user interruptions as we would leave the traced
414 * process stopped (process state T) if we would terminate in
415 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200416 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000417 */
418 if (interactive)
419 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
420
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000421 if (daemonized_tracer) {
422 pid_t pid = fork();
423 if (pid < 0) {
424 _exit(1);
425 }
426 if (pid) { /* parent */
427 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200428 * Wait for grandchild to attach to straced process
429 * (grandparent). Grandchild SIGKILLs us after it attached.
430 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000431 * it proceeds to exec the straced program.
432 */
433 pause();
434 _exit(0); /* paranoia */
435 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200436 /* grandchild */
437 /* We will be the tracer process. Remember our new pid: */
438 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000439 }
440
Roland McGrath02203312007-06-11 22:06:31 +0000441 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
442 tcp = tcbtab[tcbi];
443 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
444 continue;
445#ifdef LINUX
446 if (tcp->flags & TCB_CLONE_THREAD)
447 continue;
448#endif
449 /* Reinitialize the output since it may have changed. */
450 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200451 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000452
453#ifdef USE_PROCFS
454 if (proc_open(tcp, 1) < 0) {
455 fprintf(stderr, "trouble opening proc file\n");
456 droptcb(tcp);
457 continue;
458 }
459#else /* !USE_PROCFS */
460# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000461 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000462 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000463 DIR *dir;
464
465 sprintf(procdir, "/proc/%d/task", tcp->pid);
466 dir = opendir(procdir);
467 if (dir != NULL) {
468 unsigned int ntid = 0, nerr = 0;
469 struct dirent *de;
470 int tid;
471 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000472 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000473 continue;
474 tid = atoi(de->d_name);
475 if (tid <= 0)
476 continue;
477 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000478 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000479 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000480 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000481 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800482 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000483 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000484 tcp->parent = tcbtab[tcbi];
485 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000486 if (interactive) {
487 sigprocmask(SIG_SETMASK, &empty_set, NULL);
488 if (interrupted)
489 return;
490 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
491 }
Roland McGrath02203312007-06-11 22:06:31 +0000492 }
493 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000494 ntid -= nerr;
495 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000496 perror("attach: ptrace(PTRACE_ATTACH, ...)");
497 droptcb(tcp);
498 continue;
499 }
500 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000501 fprintf(stderr, ntid > 1
502? "Process %u attached with %u threads - interrupt to quit\n"
503: "Process %u attached - interrupt to quit\n",
504 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000505 }
506 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000507 } /* if (opendir worked) */
508 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000509# endif
510 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
511 perror("attach: ptrace(PTRACE_ATTACH, ...)");
512 droptcb(tcp);
513 continue;
514 }
515 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000516
517 if (daemonized_tracer) {
518 /*
519 * It is our grandparent we trace, not a -p PID.
520 * Don't want to just detach on exit, so...
521 */
522 tcp->flags &= ~TCB_ATTACHED;
523 /*
524 * Make parent go away.
525 * Also makes grandparent's wait() unblock.
526 */
527 kill(getppid(), SIGKILL);
528 }
529
Roland McGrath02203312007-06-11 22:06:31 +0000530#endif /* !USE_PROCFS */
531 if (!qflag)
532 fprintf(stderr,
533 "Process %u attached - interrupt to quit\n",
534 tcp->pid);
535 }
536
537 if (interactive)
538 sigprocmask(SIG_SETMASK, &empty_set, NULL);
539}
540
541static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200542startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000543{
544 struct stat statbuf;
545 const char *filename;
546 char pathname[MAXPATHLEN];
547 int pid = 0;
548 struct tcb *tcp;
549
550 filename = argv[0];
551 if (strchr(filename, '/')) {
552 if (strlen(filename) > sizeof pathname - 1) {
553 errno = ENAMETOOLONG;
554 perror("strace: exec");
555 exit(1);
556 }
557 strcpy(pathname, filename);
558 }
559#ifdef USE_DEBUGGING_EXEC
560 /*
561 * Debuggers customarily check the current directory
562 * first regardless of the path but doing that gives
563 * security geeks a panic attack.
564 */
565 else if (stat(filename, &statbuf) == 0)
566 strcpy(pathname, filename);
567#endif /* USE_DEBUGGING_EXEC */
568 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000569 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000570 int m, n, len;
571
572 for (path = getenv("PATH"); path && *path; path += m) {
573 if (strchr(path, ':')) {
574 n = strchr(path, ':') - path;
575 m = n + 1;
576 }
577 else
578 m = n = strlen(path);
579 if (n == 0) {
580 if (!getcwd(pathname, MAXPATHLEN))
581 continue;
582 len = strlen(pathname);
583 }
584 else if (n > sizeof pathname - 1)
585 continue;
586 else {
587 strncpy(pathname, path, n);
588 len = n;
589 }
590 if (len && pathname[len - 1] != '/')
591 pathname[len++] = '/';
592 strcpy(pathname + len, filename);
593 if (stat(pathname, &statbuf) == 0 &&
594 /* Accept only regular files
595 with some execute bits set.
596 XXX not perfect, might still fail */
597 S_ISREG(statbuf.st_mode) &&
598 (statbuf.st_mode & 0111))
599 break;
600 }
601 }
602 if (stat(pathname, &statbuf) < 0) {
603 fprintf(stderr, "%s: %s: command not found\n",
604 progname, filename);
605 exit(1);
606 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000607 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000608 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000609 perror("strace: fork");
610 cleanup();
611 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000612 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200613 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
614 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000615 ) {
616 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000617#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200618 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000619#ifdef MIPS
620 /* Kludge for SGI, see proc_open for details. */
621 sa.sa_handler = foobar;
622 sa.sa_flags = 0;
623 sigemptyset(&sa.sa_mask);
624 sigaction(SIGINT, &sa, NULL);
625#endif /* MIPS */
626#ifndef FREEBSD
627 pause();
628#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000629 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000630#endif /* FREEBSD */
631#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200632 if (outf != stderr)
633 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000634
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000635 if (!daemonized_tracer) {
636 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
637 perror("strace: ptrace(PTRACE_TRACEME, ...)");
638 exit(1);
639 }
640 if (debug)
641 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000642 }
Roland McGrath02203312007-06-11 22:06:31 +0000643
644 if (username != NULL || geteuid() == 0) {
645 uid_t run_euid = run_uid;
646 gid_t run_egid = run_gid;
647
648 if (statbuf.st_mode & S_ISUID)
649 run_euid = statbuf.st_uid;
650 if (statbuf.st_mode & S_ISGID)
651 run_egid = statbuf.st_gid;
652
653 /*
654 * It is important to set groups before we
655 * lose privileges on setuid.
656 */
657 if (username != NULL) {
658 if (initgroups(username, run_gid) < 0) {
659 perror("initgroups");
660 exit(1);
661 }
662 if (setregid(run_gid, run_egid) < 0) {
663 perror("setregid");
664 exit(1);
665 }
666 if (setreuid(run_uid, run_euid) < 0) {
667 perror("setreuid");
668 exit(1);
669 }
670 }
671 }
672 else
673 setreuid(run_uid, run_uid);
674
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000675 if (!daemonized_tracer) {
676 /*
677 * Induce an immediate stop so that the parent
678 * will resume us with PTRACE_SYSCALL and display
679 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400680 * Unless of course we're on a no-MMU system where
681 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000682 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400683 if (!strace_vforked)
684 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000685 } else {
686 struct sigaction sv_sigchld;
687 sigaction(SIGCHLD, NULL, &sv_sigchld);
688 /*
689 * Make sure it is not SIG_IGN, otherwise wait
690 * will not block.
691 */
692 signal(SIGCHLD, SIG_DFL);
693 /*
694 * Wait for grandchild to attach to us.
695 * It kills child after that, and wait() unblocks.
696 */
697 alarm(3);
698 wait(NULL);
699 alarm(0);
700 sigaction(SIGCHLD, &sv_sigchld, NULL);
701 }
Roland McGrath02203312007-06-11 22:06:31 +0000702#endif /* !USE_PROCFS */
703
704 execv(pathname, argv);
705 perror("strace: exec");
706 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000707 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708
709 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200710 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
711 strace_tracer_pid = getpid();
712
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000713 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 if (daemonized_tracer) {
715 /* We want subsequent startup_attach() to attach to it. */
716 tcp->flags |= TCB_ATTACHED;
717 }
Roland McGrath02203312007-06-11 22:06:31 +0000718#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 if (proc_open(tcp, 0) < 0) {
720 fprintf(stderr, "trouble opening proc file\n");
721 cleanup();
722 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000723 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000724#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000725}
726
Wang Chaob13c0de2010-11-12 17:25:19 +0800727#ifdef LINUX
728/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000729 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800730 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000731 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800732 */
733static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200734test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800735{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000736 int pid, expected_grandchild = 0, found_grandchild = 0;
737 const unsigned int test_options = PTRACE_O_TRACECLONE |
738 PTRACE_O_TRACEFORK |
739 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800740
741 if ((pid = fork()) < 0)
742 return -1;
743 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000744 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800745 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800746 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000747 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800748 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000749
750 while (1) {
751 int status, tracee_pid;
752
753 tracee_pid = wait(&status);
754 if (tracee_pid == -1) {
755 if (errno == EINTR)
756 continue;
757 else if (errno == ECHILD)
758 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200759 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000760 return -1;
761 }
762 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000763 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000764 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
765 errno != ESRCH)
766 kill(tracee_pid, SIGKILL);
767 }
768 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000769 switch (WSTOPSIG(status)) {
770 case SIGSTOP:
771 if (ptrace(PTRACE_SETOPTIONS, pid,
772 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000773 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800774 return -1;
775 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000776 break;
777 case SIGTRAP:
778 if (status >> 16 == PTRACE_EVENT_FORK) {
779 long msg = 0;
780
781 if (ptrace(PTRACE_GETEVENTMSG, pid,
782 NULL, (long) &msg) == 0)
783 expected_grandchild = msg;
784 }
785 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800786 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000787 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
788 errno != ESRCH)
789 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800790 }
791 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000792 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200793 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800794 return 0;
795}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200796
797/*
798 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
799 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
800 * and then see whether it will stop with (SIGTRAP | 0x80).
801 *
802 * Use of this option enables correct handling of user-generated SIGTRAPs,
803 * and SIGTRAPs generated by special instructions such as int3 on x86:
804 * _start: .globl _start
805 * int3
806 * movl $42, %ebx
807 * movl $1, %eax
808 * int $0x80
809 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
810 */
811static void
812test_ptrace_setoptions_for_all(void)
813{
814 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
815 int pid;
816 int it_worked = 0;
817
818 pid = fork();
819 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200820 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200821
822 if (pid == 0) {
823 pid = getpid();
824 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200825 /* Note: exits with exitcode 1 */
826 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200827 kill(pid, SIGSTOP);
828 _exit(0); /* parent should see entry into this syscall */
829 }
830
831 while (1) {
832 int status, tracee_pid;
833
834 errno = 0;
835 tracee_pid = wait(&status);
836 if (tracee_pid <= 0) {
837 if (errno == EINTR)
838 continue;
839 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200840 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200841 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200842 if (WIFEXITED(status)) {
843 if (WEXITSTATUS(status) == 0)
844 break;
845 /* PTRACE_TRACEME failed in child. This is fatal. */
846 exit(1);
847 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200848 if (!WIFSTOPPED(status)) {
849 kill(pid, SIGKILL);
850 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
851 }
852 if (WSTOPSIG(status) == SIGSTOP) {
853 /*
854 * We don't check "options aren't accepted" error.
855 * If it happens, we'll never get (SIGTRAP | 0x80),
856 * and thus will decide to not use the option.
857 * IOW: the outcome of the test will be correct.
858 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200859 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
860 if (errno != EINVAL)
861 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200862 }
863 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
864 it_worked = 1;
865 }
866 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
867 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200868 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200869 }
870 }
871
872 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200873 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200874 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200875 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200876 fprintf(stderr, "ptrace_setoptions = %#x\n",
877 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200878 return;
879 }
880
881 fprintf(stderr,
882 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
883}
Wang Chaob13c0de2010-11-12 17:25:19 +0800884#endif
885
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000887main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000889 struct tcb *tcp;
890 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000891 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000892 struct sigaction sa;
893
894 static char buf[BUFSIZ];
895
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000896 progname = argv[0] ? argv[0] : "strace";
897
Denys Vlasenko75422762011-05-27 14:36:01 +0200898 strace_tracer_pid = getpid();
899
Roland McGrathee9d4352002-12-18 04:16:10 +0000900 /* Allocate the initial tcbtab. */
901 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000902 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000903 fprintf(stderr, "%s: out of memory\n", progname);
904 exit(1);
905 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000906 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000907 fprintf(stderr, "%s: out of memory\n", progname);
908 exit(1);
909 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000910 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
911 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
912
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000913 outf = stderr;
914 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000915 set_sortby(DEFAULT_SORTBY);
916 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 qualify("trace=all");
918 qualify("abbrev=all");
919 qualify("verbose=all");
920 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000921 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000922 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000923#ifndef USE_PROCFS
924 "D"
925#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000926 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 switch (c) {
928 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000929 if (cflag == CFLAG_BOTH) {
930 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
931 progname);
932 exit(1);
933 }
934 cflag = CFLAG_ONLY_STATS;
935 break;
936 case 'C':
937 if (cflag == CFLAG_ONLY_STATS) {
938 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
939 progname);
940 exit(1);
941 }
942 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000943 break;
944 case 'd':
945 debug++;
946 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000947#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000948 case 'D':
949 daemonized_tracer = 1;
950 break;
951#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000952 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000953 optF = 1;
954 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 case 'f':
956 followfork++;
957 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 case 'h':
959 usage(stdout, 0);
960 break;
961 case 'i':
962 iflag++;
963 break;
964 case 'q':
965 qflag++;
966 break;
967 case 'r':
968 rflag++;
969 tflag++;
970 break;
971 case 't':
972 tflag++;
973 break;
974 case 'T':
975 dtime++;
976 break;
977 case 'x':
978 xflag++;
979 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000980 case 'y':
981 show_fd_path = 1;
982 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 case 'v':
984 qualify("abbrev=none");
985 break;
986 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000987 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 exit(0);
989 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000990 case 'z':
991 not_failing_only = 1;
992 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993 case 'a':
994 acolumn = atoi(optarg);
995 break;
996 case 'e':
997 qualify(optarg);
998 break;
999 case 'o':
1000 outfname = strdup(optarg);
1001 break;
1002 case 'O':
1003 set_overhead(atoi(optarg));
1004 break;
1005 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +00001006 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 fprintf(stderr, "%s: Invalid process id: %s\n",
1008 progname, optarg);
1009 break;
1010 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001011 if (pid == strace_tracer_pid) {
Wichert Akkerman54a47671999-10-17 00:57:34 +00001012 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 break;
1014 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001015 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016 tcp->flags |= TCB_ATTACHED;
1017 pflag_seen++;
1018 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001019 case 'P':
1020 tracing_paths = 1;
1021 if (pathtrace_select(optarg)) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001022 fprintf(stderr, "%s : failed to select path '%s'\n", progname, optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001023 exit(1);
1024 }
1025 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 case 's':
1027 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001028 if (max_strlen < 0) {
1029 fprintf(stderr,
1030 "%s: invalid -s argument: %s\n",
1031 progname, optarg);
1032 exit(1);
1033 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 break;
1035 case 'S':
1036 set_sortby(optarg);
1037 break;
1038 case 'u':
1039 username = strdup(optarg);
1040 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001041 case 'E':
1042 if (putenv(optarg) < 0) {
1043 fprintf(stderr, "%s: out of memory\n",
1044 progname);
1045 exit(1);
1046 }
1047 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 default:
1049 usage(stderr, 1);
1050 break;
1051 }
1052 }
1053
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001054 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001055 usage(stderr, 1);
1056
Wang Chaod322a4b2010-08-05 14:30:11 +08001057 if (pflag_seen && daemonized_tracer) {
1058 fprintf(stderr,
1059 "%s: -D and -p are mutually exclusive options\n",
1060 progname);
1061 exit(1);
1062 }
1063
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001064 if (!followfork)
1065 followfork = optF;
1066
Roland McGrathcb9def62006-04-25 07:48:03 +00001067 if (followfork > 1 && cflag) {
1068 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001069 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +00001070 progname);
1071 exit(1);
1072 }
1073
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 /* See if they want to run as another user. */
1075 if (username != NULL) {
1076 struct passwd *pent;
1077
1078 if (getuid() != 0 || geteuid() != 0) {
1079 fprintf(stderr,
1080 "%s: you must be root to use the -u option\n",
1081 progname);
1082 exit(1);
1083 }
1084 if ((pent = getpwnam(username)) == NULL) {
1085 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +00001086 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 exit(1);
1088 }
1089 run_uid = pent->pw_uid;
1090 run_gid = pent->pw_gid;
1091 }
1092 else {
1093 run_uid = getuid();
1094 run_gid = getgid();
1095 }
1096
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001097#ifdef LINUX
1098 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001099 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001100 fprintf(stderr,
1101 "Test for options supported by PTRACE_SETOPTIONS "
1102 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001103 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001104 }
1105 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001106 fprintf(stderr, "ptrace_setoptions = %#x\n",
1107 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001108 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001109 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001110#endif
1111
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 /* Check if they want to redirect the output. */
1113 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001114 /* See if they want to pipe the output. */
1115 if (outfname[0] == '|' || outfname[0] == '!') {
1116 /*
1117 * We can't do the <outfname>.PID funny business
1118 * when using popen, so prohibit it.
1119 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001120 if (followfork > 1)
1121 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1122 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001123 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001124 else if (followfork <= 1)
1125 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126 }
1127
Roland McGrath37b9a662003-11-07 02:26:54 +00001128 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +00001130 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001133 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001134
Roland McGrath54cc1c82007-11-03 23:34:11 +00001135 /* Valid states here:
1136 optind < argc pflag_seen outfname interactive
1137 1 0 0 1
1138 0 1 0 1
1139 1 0 1 0
1140 0 1 1 1
1141 */
1142
1143 /* STARTUP_CHILD must be called before the signal handlers get
1144 installed below as they are inherited into the spawned process.
1145 Also we do not need to be protected by them as during interruption
1146 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1147 if (!pflag_seen)
1148 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 sigemptyset(&empty_set);
1151 sigemptyset(&blocked_set);
1152 sa.sa_handler = SIG_IGN;
1153 sigemptyset(&sa.sa_mask);
1154 sa.sa_flags = 0;
1155 sigaction(SIGTTOU, &sa, NULL);
1156 sigaction(SIGTTIN, &sa, NULL);
1157 if (interactive) {
1158 sigaddset(&blocked_set, SIGHUP);
1159 sigaddset(&blocked_set, SIGINT);
1160 sigaddset(&blocked_set, SIGQUIT);
1161 sigaddset(&blocked_set, SIGPIPE);
1162 sigaddset(&blocked_set, SIGTERM);
1163 sa.sa_handler = interrupt;
1164#ifdef SUNOS4
1165 /* POSIX signals on sunos4.1 are a little broken. */
1166 sa.sa_flags = SA_INTERRUPT;
1167#endif /* SUNOS4 */
1168 }
1169 sigaction(SIGHUP, &sa, NULL);
1170 sigaction(SIGINT, &sa, NULL);
1171 sigaction(SIGQUIT, &sa, NULL);
1172 sigaction(SIGPIPE, &sa, NULL);
1173 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001174#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 sa.sa_handler = reaper;
1176 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001177#else
1178 /* Make sure SIGCHLD has the default action so that waitpid
1179 definitely works without losing track of children. The user
1180 should not have given us a bogus state to inherit, but he might
1181 have. Arguably we should detect SIG_IGN here and pass it on
1182 to children, but probably noone really needs that. */
1183 sa.sa_handler = SIG_DFL;
1184 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001185#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001187 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001188 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001189
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 if (trace() < 0)
1191 exit(1);
1192 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001193 fflush(NULL);
1194 if (exit_code > 0xff) {
1195 /* Child was killed by a signal, mimic that. */
1196 exit_code &= 0xff;
1197 signal(exit_code, SIG_DFL);
1198 raise(exit_code);
1199 /* Paranoia - what if this signal is not fatal?
1200 Exit with 128 + signo then. */
1201 exit_code += 128;
1202 }
1203 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204}
1205
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001206static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001207expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001208{
1209 /* Allocate some more TCBs and expand the table.
1210 We don't want to relocate the TCBs because our
1211 callers have pointers and it would be a pain.
1212 So tcbtab is a table of pointers. Since we never
1213 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001214 int i = tcbtabsize;
1215 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1216 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1217 if (newtab == NULL || newtcbs == NULL)
1218 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001219 tcbtabsize *= 2;
1220 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001221 while (i < tcbtabsize)
1222 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001223}
1224
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001226alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227{
1228 int i;
1229 struct tcb *tcp;
1230
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001231 if (nprocs == tcbtabsize)
1232 expand_tcbtab();
1233
Roland McGrathee9d4352002-12-18 04:16:10 +00001234 for (i = 0; i < tcbtabsize; i++) {
1235 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001237 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 tcp->flags = TCB_INUSE | TCB_STARTUP;
1240 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 tcp->pfd = -1;
1242 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001243 if (command_options_parsed)
1244 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 return tcp;
1246 }
1247 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001248 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249}
1250
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001253proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254{
1255 char proc[32];
1256 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001257#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001258 int i;
1259 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260 sigset_t signals;
1261 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001262#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263#ifndef HAVE_POLLABLE_PROCFS
1264 static int last_pfd;
1265#endif
1266
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001267#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001268 /* Open the process pseudo-files in /proc. */
1269 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1270 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 perror("strace: open(\"/proc/...\", ...)");
1272 return -1;
1273 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001274 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001275 sprintf(proc, "/proc/%d/status", tcp->pid);
1276 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1277 perror("strace: open(\"/proc/...\", ...)");
1278 return -1;
1279 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001280 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001281 sprintf(proc, "/proc/%d/as", tcp->pid);
1282 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1283 perror("strace: open(\"/proc/...\", ...)");
1284 return -1;
1285 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001286 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001287#else
1288 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001289#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001290 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001291 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001292#else /* FREEBSD */
1293 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001294 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001295#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001296 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001297 perror("strace: open(\"/proc/...\", ...)");
1298 return -1;
1299 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001300 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001301#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001302#ifdef FREEBSD
1303 sprintf(proc, "/proc/%d/regs", tcp->pid);
1304 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1305 perror("strace: open(\"/proc/.../regs\", ...)");
1306 return -1;
1307 }
1308 if (cflag) {
1309 sprintf(proc, "/proc/%d/status", tcp->pid);
1310 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1311 perror("strace: open(\"/proc/.../status\", ...)");
1312 return -1;
1313 }
1314 } else
1315 tcp->pfd_status = -1;
1316#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001317 rebuild_pollv();
1318 if (!attaching) {
1319 /*
1320 * Wait for the child to pause. Because of a race
1321 * condition we have to poll for the event.
1322 */
1323 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001324 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001325 perror("strace: PIOCSTATUS");
1326 return -1;
1327 }
1328 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001329 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001330 }
1331 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001332#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001333 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001334 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001335 perror("strace: PIOCSTOP");
1336 return -1;
1337 }
Roland McGrath553a6092002-12-16 20:40:39 +00001338#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339#ifdef PIOCSET
1340 /* Set Run-on-Last-Close. */
1341 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001342 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001343 perror("PIOCSET PR_RLC");
1344 return -1;
1345 }
1346 /* Set or Reset Inherit-on-Fork. */
1347 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001348 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001349 perror("PIOC{SET,RESET} PR_FORK");
1350 return -1;
1351 }
1352#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001353#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1355 perror("PIOCSRLC");
1356 return -1;
1357 }
1358 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1359 perror("PIOC{S,R}FORK");
1360 return -1;
1361 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001362#else /* FREEBSD */
1363 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1364 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1365 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001366 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001367 }
1368 arg &= ~PF_LINGER;
1369 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001370 perror("PIOCSFL");
1371 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001372 }
1373#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001375#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001376 /* Enable all syscall entries we care about. */
1377 premptyset(&syscalls);
1378 for (i = 1; i < MAX_QUALS; ++i) {
1379 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001380 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001381 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001382 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001383 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001384 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001385#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001386 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001387#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001388#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001389 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001390#endif
1391#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001392 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001393#endif
1394#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001395 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001396#endif
1397 }
1398 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001399 perror("PIOCSENTRY");
1400 return -1;
1401 }
John Hughes19e49982001-10-19 08:59:12 +00001402 /* Enable the syscall exits. */
1403 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 perror("PIOSEXIT");
1405 return -1;
1406 }
John Hughes19e49982001-10-19 08:59:12 +00001407 /* Enable signals we care about. */
1408 premptyset(&signals);
1409 for (i = 1; i < MAX_QUALS; ++i) {
1410 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001411 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001412 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001413 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414 perror("PIOCSTRACE");
1415 return -1;
1416 }
John Hughes19e49982001-10-19 08:59:12 +00001417 /* Enable faults we care about */
1418 premptyset(&faults);
1419 for (i = 1; i < MAX_QUALS; ++i) {
1420 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001421 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001422 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001423 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424 perror("PIOCSFAULT");
1425 return -1;
1426 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001427#else /* FREEBSD */
1428 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001429 arg = S_SIG | S_SCE | S_SCX;
1430 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001431 perror("PIOCBIS");
1432 return -1;
1433 }
1434#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 if (!attaching) {
1436#ifdef MIPS
1437 /*
1438 * The SGI PRSABORT doesn't work for pause() so
1439 * we send it a caught signal to wake it up.
1440 */
1441 kill(tcp->pid, SIGINT);
1442#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001443#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001445 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001446 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 perror("PIOCRUN");
1448 return -1;
1449 }
Roland McGrath553a6092002-12-16 20:40:39 +00001450#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001451#endif /* !MIPS*/
1452#ifdef FREEBSD
1453 /* wake up the child if it received the SIGSTOP */
1454 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001455#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456 for (;;) {
1457 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001458 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 perror("PIOCWSTOP");
1460 return -1;
1461 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001462 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001463 tcp->flags &= ~TCB_INSYSCALL;
1464 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001465 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001466 break;
1467 }
1468 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001469#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001470 arg = 0;
1471 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001472#else /* FREEBSD */
1473 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001474#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475 perror("PIOCRUN");
1476 return -1;
1477 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001478#ifdef FREEBSD
1479 /* handle the case where we "opened" the child before
1480 it did the kill -STOP */
1481 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1482 tcp->status.PR_WHAT == SIGSTOP)
1483 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001484#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001486#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001488#else /* FREEBSD */
1489 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001490 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001491 /* We are attaching to an already running process.
1492 * Try to figure out the state of the process in syscalls,
1493 * to handle the first event well.
1494 * This is done by having a look at the "wchan" property of the
1495 * process, which tells where it is stopped (if it is). */
1496 FILE * status;
1497 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001498
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001499 sprintf(proc, "/proc/%d/status", tcp->pid);
1500 status = fopen(proc, "r");
1501 if (status &&
1502 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1503 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1504 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1505 strcmp(wchan, "stopevent")) {
1506 /* The process is asleep in the middle of a syscall.
1507 Fake the syscall entry event */
1508 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1509 tcp->status.PR_WHY = PR_SYSENTRY;
1510 trace_syscall(tcp);
1511 }
1512 if (status)
1513 fclose(status);
1514 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001515 }
1516#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517#ifndef HAVE_POLLABLE_PROCFS
1518 if (proc_poll_pipe[0] != -1)
1519 proc_poller(tcp->pfd);
1520 else if (nprocs > 1) {
1521 proc_poll_open();
1522 proc_poller(last_pfd);
1523 proc_poller(tcp->pfd);
1524 }
1525 last_pfd = tcp->pfd;
1526#endif /* !HAVE_POLLABLE_PROCFS */
1527 return 0;
1528}
1529
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001530#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001532struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001533pid2tcb(int pid)
1534{
1535 int i;
1536
1537 if (pid <= 0)
1538 return NULL;
1539
1540 for (i = 0; i < tcbtabsize; i++) {
1541 struct tcb *tcp = tcbtab[i];
1542 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1543 return tcp;
1544 }
1545
1546 return NULL;
1547}
1548
1549#ifdef USE_PROCFS
1550
1551static struct tcb *
1552first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553{
1554 int i;
1555 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001556 for (i = 0; i < tcbtabsize; i++) {
1557 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558 if (tcp->flags & TCB_INUSE)
1559 return tcp;
1560 }
1561 return NULL;
1562}
1563
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001565pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566{
1567 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568
Roland McGrathca16be82003-01-10 19:55:28 +00001569 for (i = 0; i < tcbtabsize; i++) {
1570 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571 if (tcp->pfd != pfd)
1572 continue;
1573 if (tcp->flags & TCB_INUSE)
1574 return tcp;
1575 }
1576 return NULL;
1577}
1578
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001579#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580
1581void
Denys Vlasenko12014262011-05-30 14:00:14 +02001582droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583{
1584 if (tcp->pid == 0)
1585 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001586#ifdef TCB_CLONE_THREAD
1587 if (tcp->nclone_threads > 0) {
1588 /* There are other threads left in this process, but this
1589 is the one whose PID represents the whole process.
1590 We need to keep this record around as a zombie until
1591 all the threads die. */
1592 tcp->flags |= TCB_EXITING;
1593 return;
1594 }
1595#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596 nprocs--;
1597 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001598
Roland McGrathe29341c2003-01-10 20:14:20 +00001599 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001600#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001601 if (tcp->flags & TCB_CLONE_THREAD)
1602 tcp->parent->nclone_threads--;
1603#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001604#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001605 /* Update fields like NCLONE_DETACHED, only
1606 for zombie group leader that has already reported
1607 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001608 function. The same condition as at the top of DETACH. */
1609 if ((tcp->flags & TCB_CLONE_THREAD) &&
1610 tcp->parent->nclone_threads == 0 &&
1611 (tcp->parent->flags & TCB_EXITING))
1612 droptcb(tcp->parent);
1613#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001614 tcp->parent = NULL;
1615 }
1616
1617 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618 if (tcp->pfd != -1) {
1619 close(tcp->pfd);
1620 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001621#ifdef FREEBSD
1622 if (tcp->pfd_reg != -1) {
1623 close(tcp->pfd_reg);
1624 tcp->pfd_reg = -1;
1625 }
1626 if (tcp->pfd_status != -1) {
1627 close(tcp->pfd_status);
1628 tcp->pfd_status = -1;
1629 }
Roland McGrath553a6092002-12-16 20:40:39 +00001630#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001631#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001632 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633#endif
1634 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001635
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001636 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001638
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 tcp->outf = 0;
1640}
1641
Roland McGrath0a463882007-07-05 18:43:16 +00001642/* detach traced process; continue with sig
1643 Never call DETACH twice on the same process as both unattached and
1644 attached-unstopped processes give the same ESRCH. For unattached process we
1645 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646
1647static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001648detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649{
1650 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001651#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001652 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001653 struct tcb *zombie = NULL;
1654
1655 /* If the group leader is lingering only because of this other
1656 thread now dying, then detach the leader as well. */
1657 if ((tcp->flags & TCB_CLONE_THREAD) &&
1658 tcp->parent->nclone_threads == 1 &&
1659 (tcp->parent->flags & TCB_EXITING))
1660 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001661#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662
1663 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001664 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665
1666#ifdef LINUX
1667 /*
1668 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001669 * before detaching. Arghh. We go through hoops
1670 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001672#if defined(SPARC)
1673#undef PTRACE_DETACH
1674#define PTRACE_DETACH PTRACE_SUNDETACH
1675#endif
Roland McGrath02203312007-06-11 22:06:31 +00001676 /*
1677 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1678 * expected SIGSTOP. We must catch exactly one as otherwise the
1679 * detached process would be left stopped (process state T).
1680 */
1681 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001682 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1683 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001684 }
1685 else if (errno != ESRCH) {
1686 /* Shouldn't happen. */
1687 perror("detach: ptrace(PTRACE_DETACH, ...)");
1688 }
Roland McGrath134813a2007-06-02 00:07:33 +00001689 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1690 : tcp->pid),
1691 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001692 if (errno != ESRCH)
1693 perror("detach: checking sanity");
1694 }
Roland McGrath02203312007-06-11 22:06:31 +00001695 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1696 ? tcp->parent->pid : tcp->pid),
1697 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001698 if (errno != ESRCH)
1699 perror("detach: stopping child");
1700 }
Roland McGrath02203312007-06-11 22:06:31 +00001701 else
1702 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001703 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001705#ifdef __WALL
1706 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1707 if (errno == ECHILD) /* Already gone. */
1708 break;
1709 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001710 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001711 break;
1712 }
1713#endif /* __WALL */
1714 /* No __WALL here. */
1715 if (waitpid(tcp->pid, &status, 0) < 0) {
1716 if (errno != ECHILD) {
1717 perror("detach: waiting");
1718 break;
1719 }
1720#ifdef __WCLONE
1721 /* If no processes, try clones. */
1722 if (wait4(tcp->pid, &status, __WCLONE,
1723 NULL) < 0) {
1724 if (errno != ECHILD)
1725 perror("detach: waiting");
1726 break;
1727 }
1728#endif /* __WCLONE */
1729 }
1730#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001731 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001732#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733 if (!WIFSTOPPED(status)) {
1734 /* Au revoir, mon ami. */
1735 break;
1736 }
1737 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001738 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 break;
1740 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001741 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001742 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001743 : WSTOPSIG(status));
1744 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001747 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001748#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749
1750#if defined(SUNOS4)
1751 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1752 if (sig && kill(tcp->pid, sig) < 0)
1753 perror("detach: kill");
1754 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001755 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756#endif /* SUNOS4 */
1757
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758 if (!qflag)
1759 fprintf(stderr, "Process %u detached\n", tcp->pid);
1760
1761 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001762
1763#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001764 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001765 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001766 droptcb(zombie);
1767 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001768#endif
1769
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770 return error;
1771}
1772
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001773#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001775static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776{
1777 int pid;
1778 int status;
1779
1780 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 }
1782}
1783
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001784#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785
1786static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001787cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788{
1789 int i;
1790 struct tcb *tcp;
1791
Roland McGrathee9d4352002-12-18 04:16:10 +00001792 for (i = 0; i < tcbtabsize; i++) {
1793 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 if (!(tcp->flags & TCB_INUSE))
1795 continue;
1796 if (debug)
1797 fprintf(stderr,
1798 "cleanup: looking at pid %u\n", tcp->pid);
1799 if (tcp_last &&
1800 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001801 tprintf(" <unfinished ...>");
1802 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803 }
1804 if (tcp->flags & TCB_ATTACHED)
1805 detach(tcp, 0);
1806 else {
1807 kill(tcp->pid, SIGCONT);
1808 kill(tcp->pid, SIGTERM);
1809 }
1810 }
1811 if (cflag)
1812 call_summary(outf);
1813}
1814
1815static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001816interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817{
1818 interrupted = 1;
1819}
1820
1821#ifndef HAVE_STRERROR
1822
Roland McGrath6d2b3492002-12-30 00:51:30 +00001823#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824extern int sys_nerr;
1825extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001826#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001827
1828const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001829strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830{
1831 static char buf[64];
1832
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001833 if (err_no < 1 || err_no >= sys_nerr) {
1834 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001835 return buf;
1836 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001837 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838}
1839
1840#endif /* HAVE_STERRROR */
1841
1842#ifndef HAVE_STRSIGNAL
1843
Roland McGrath8f474e02003-01-14 07:53:33 +00001844#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001845extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001847#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1848extern char *_sys_siglist[];
1849#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001850
1851const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001852strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853{
1854 static char buf[64];
1855
1856 if (sig < 1 || sig >= NSIG) {
1857 sprintf(buf, "Unknown signal %d", sig);
1858 return buf;
1859 }
1860#ifdef HAVE__SYS_SIGLIST
1861 return _sys_siglist[sig];
1862#else
1863 return sys_siglist[sig];
1864#endif
1865}
1866
1867#endif /* HAVE_STRSIGNAL */
1868
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001869#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870
1871static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001872rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873{
1874 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875
Roland McGrathee9d4352002-12-18 04:16:10 +00001876 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001877 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001878 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001879 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001880 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001881 exit(1);
1882 }
1883
Roland McGrathca16be82003-01-10 19:55:28 +00001884 for (i = j = 0; i < tcbtabsize; i++) {
1885 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 if (!(tcp->flags & TCB_INUSE))
1887 continue;
1888 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001889 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890 j++;
1891 }
1892 if (j != nprocs) {
1893 fprintf(stderr, "strace: proc miscount\n");
1894 exit(1);
1895 }
1896}
1897
1898#ifndef HAVE_POLLABLE_PROCFS
1899
1900static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001901proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903 int i;
1904
1905 if (pipe(proc_poll_pipe) < 0) {
1906 perror("pipe");
1907 exit(1);
1908 }
1909 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001910 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 }
1912}
1913
1914static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001915proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001916{
1917 int i;
1918 int n;
1919 struct proc_pollfd pollinfo;
1920
1921 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1922 return n;
1923 if (n != sizeof(struct proc_pollfd)) {
1924 fprintf(stderr, "panic: short read: %d\n", n);
1925 exit(1);
1926 }
1927 for (i = 0; i < nprocs; i++) {
1928 if (pollv[i].fd == pollinfo.fd)
1929 pollv[i].revents = pollinfo.revents;
1930 else
1931 pollv[i].revents = 0;
1932 }
1933 poller_pid = pollinfo.pid;
1934 return 1;
1935}
1936
1937static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001938wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001939{
1940}
1941
1942static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001943proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001944{
1945 struct proc_pollfd pollinfo;
1946 struct sigaction sa;
1947 sigset_t blocked_set, empty_set;
1948 int i;
1949 int n;
1950 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001951#ifdef FREEBSD
1952 struct procfs_status pfs;
1953#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001954
1955 switch (fork()) {
1956 case -1:
1957 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001958 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959 case 0:
1960 break;
1961 default:
1962 return;
1963 }
1964
1965 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1966 sa.sa_flags = 0;
1967 sigemptyset(&sa.sa_mask);
1968 sigaction(SIGHUP, &sa, NULL);
1969 sigaction(SIGINT, &sa, NULL);
1970 sigaction(SIGQUIT, &sa, NULL);
1971 sigaction(SIGPIPE, &sa, NULL);
1972 sigaction(SIGTERM, &sa, NULL);
1973 sa.sa_handler = wakeup_handler;
1974 sigaction(SIGUSR1, &sa, NULL);
1975 sigemptyset(&blocked_set);
1976 sigaddset(&blocked_set, SIGUSR1);
1977 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1978 sigemptyset(&empty_set);
1979
1980 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1981 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001982 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983 }
1984 n = rl.rlim_cur;
1985 for (i = 0; i < n; i++) {
1986 if (i != pfd && i != proc_poll_pipe[1])
1987 close(i);
1988 }
1989
1990 pollinfo.fd = pfd;
1991 pollinfo.pid = getpid();
1992 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001993#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001994 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1995#else
1996 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1997#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001998 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001999 switch (errno) {
2000 case EINTR:
2001 continue;
2002 case EBADF:
2003 pollinfo.revents = POLLERR;
2004 break;
2005 case ENOENT:
2006 pollinfo.revents = POLLHUP;
2007 break;
2008 default:
2009 perror("proc_poller: PIOCWSTOP");
2010 }
2011 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2012 _exit(0);
2013 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002014 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2016 sigsuspend(&empty_set);
2017 }
2018}
2019
2020#endif /* !HAVE_POLLABLE_PROCFS */
2021
2022static int
2023choose_pfd()
2024{
2025 int i, j;
2026 struct tcb *tcp;
2027
2028 static int last;
2029
2030 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002031 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002032 /*
2033 * The previous process is ready to run again. We'll
2034 * let it do so if it is currently in a syscall. This
2035 * heuristic improves the readability of the trace.
2036 */
2037 tcp = pfd2tcb(pollv[last].fd);
2038 if (tcp && (tcp->flags & TCB_INSYSCALL))
2039 return pollv[last].fd;
2040 }
2041
2042 for (i = 0; i < nprocs; i++) {
2043 /* Let competing children run round robin. */
2044 j = (i + last + 1) % nprocs;
2045 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2046 tcp = pfd2tcb(pollv[j].fd);
2047 if (!tcp) {
2048 fprintf(stderr, "strace: lost proc\n");
2049 exit(1);
2050 }
2051 droptcb(tcp);
2052 return -1;
2053 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002054 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 last = j;
2056 return pollv[j].fd;
2057 }
2058 }
2059 fprintf(stderr, "strace: nothing ready\n");
2060 exit(1);
2061}
2062
2063static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002064trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002066#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002067 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002068#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002069 struct tcb *tcp;
2070 int pfd;
2071 int what;
2072 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002073 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002074
2075 for (;;) {
2076 if (interactive)
2077 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2078
2079 if (nprocs == 0)
2080 break;
2081
2082 switch (nprocs) {
2083 case 1:
2084#ifndef HAVE_POLLABLE_PROCFS
2085 if (proc_poll_pipe[0] == -1) {
2086#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002087 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002088 if (!tcp)
2089 continue;
2090 pfd = tcp->pfd;
2091 if (pfd == -1)
2092 continue;
2093 break;
2094#ifndef HAVE_POLLABLE_PROCFS
2095 }
2096 /* fall through ... */
2097#endif /* !HAVE_POLLABLE_PROCFS */
2098 default:
2099#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002100#ifdef POLL_HACK
2101 /* On some systems (e.g. UnixWare) we get too much ugly
2102 "unfinished..." stuff when multiple proceses are in
2103 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002104
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002105 if (in_syscall) {
2106 struct pollfd pv;
2107 tcp = in_syscall;
2108 in_syscall = NULL;
2109 pv.fd = tcp->pfd;
2110 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002111 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002112 if (interrupted)
2113 return 0;
2114 continue;
2115 }
2116 else if (what == 1 && pv.revents & POLLWANT) {
2117 goto FOUND;
2118 }
2119 }
2120#endif
2121
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002122 if (poll(pollv, nprocs, INFTIM) < 0) {
2123 if (interrupted)
2124 return 0;
2125 continue;
2126 }
2127#else /* !HAVE_POLLABLE_PROCFS */
2128 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2129 if (interrupted)
2130 return 0;
2131 continue;
2132 }
2133#endif /* !HAVE_POLLABLE_PROCFS */
2134 pfd = choose_pfd();
2135 if (pfd == -1)
2136 continue;
2137 break;
2138 }
2139
2140 /* Look up `pfd' in our table. */
2141 if ((tcp = pfd2tcb(pfd)) == NULL) {
2142 fprintf(stderr, "unknown pfd: %u\n", pfd);
2143 exit(1);
2144 }
John Hughesb6643082002-05-23 11:02:22 +00002145#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002146 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002147#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 /* Get the status of the process. */
2149 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002150#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002151 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002152#else /* FREEBSD */
2153 /* Thanks to some scheduling mystery, the first poller
2154 sometimes waits for the already processed end of fork
2155 event. Doing a non blocking poll here solves the problem. */
2156 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002157 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002158 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002159 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002160#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002161 ioctl_errno = errno;
2162#ifndef HAVE_POLLABLE_PROCFS
2163 if (proc_poll_pipe[0] != -1) {
2164 if (ioctl_result < 0)
2165 kill(poller_pid, SIGKILL);
2166 else
2167 kill(poller_pid, SIGUSR1);
2168 }
2169#endif /* !HAVE_POLLABLE_PROCFS */
2170 }
2171 if (interrupted)
2172 return 0;
2173
2174 if (interactive)
2175 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2176
2177 if (ioctl_result < 0) {
2178 /* Find out what happened if it failed. */
2179 switch (ioctl_errno) {
2180 case EINTR:
2181 case EBADF:
2182 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002183#ifdef FREEBSD
2184 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002185#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 case ENOENT:
2187 droptcb(tcp);
2188 continue;
2189 default:
2190 perror("PIOCWSTOP");
2191 exit(1);
2192 }
2193 }
2194
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002195#ifdef FREEBSD
2196 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2197 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002198 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002199 continue;
2200 }
Roland McGrath553a6092002-12-16 20:40:39 +00002201#endif
2202
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 /* clear the just started flag */
2204 tcp->flags &= ~TCB_STARTUP;
2205
2206 /* set current output file */
2207 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002208 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209
2210 if (cflag) {
2211 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002212#ifdef FREEBSD
2213 char buf[1024];
2214 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002215
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002216 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2217 buf[len] = '\0';
2218 sscanf(buf,
2219 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2220 &stime.tv_sec, &stime.tv_usec);
2221 } else
2222 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002223#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2225 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002226#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2228 tcp->stime = stime;
2229 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002230 what = tcp->status.PR_WHAT;
2231 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002232#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002234 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2235 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 if (trace_syscall(tcp) < 0) {
2237 fprintf(stderr, "syscall trouble\n");
2238 exit(1);
2239 }
2240 }
2241 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002242#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002243 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002244#ifdef POLL_HACK
2245 in_syscall = tcp;
2246#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002247 case PR_SYSEXIT:
2248 if (trace_syscall(tcp) < 0) {
2249 fprintf(stderr, "syscall trouble\n");
2250 exit(1);
2251 }
2252 break;
2253 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002254 if (cflag != CFLAG_ONLY_STATS
2255 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 printleader(tcp);
2257 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002258 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002259 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002260#ifdef PR_INFO
2261 if (tcp->status.PR_INFO.si_signo == what) {
2262 printleader(tcp);
2263 tprintf(" siginfo=");
2264 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002265 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002266 }
2267#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002268 }
2269 break;
2270 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002271 if (cflag != CFLAGS_ONLY_STATS
2272 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002273 printleader(tcp);
2274 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002275 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002276 }
2277 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002278#ifdef FREEBSD
2279 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002280 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002281#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002282 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002283 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002284 exit(1);
2285 break;
2286 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002287 /* Remember current print column before continuing. */
2288 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002289 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002290#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002291 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002292#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002293 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002294#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002295 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002296 perror("PIOCRUN");
2297 exit(1);
2298 }
2299 }
2300 return 0;
2301}
2302
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002303#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002304
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002305#ifdef TCB_GROUP_EXITING
2306/* Handle an exit detach or death signal that is taking all the
2307 related clone threads with it. This is called in three circumstances:
2308 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2309 SIG == 0 Continuing TCP will perform an exit_group syscall.
2310 SIG == other Continuing TCP with SIG will kill the process.
2311*/
2312static int
2313handle_group_exit(struct tcb *tcp, int sig)
2314{
2315 /* We need to locate our records of all the clone threads
2316 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002317 struct tcb *leader = NULL;
2318
2319 if (tcp->flags & TCB_CLONE_THREAD)
2320 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002321
2322 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002323 if (leader != NULL && leader != tcp
2324 && !(leader->flags & TCB_GROUP_EXITING)
2325 && !(tcp->flags & TCB_STARTUP)
2326 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002327 fprintf(stderr,
2328 "PANIC: handle_group_exit: %d leader %d\n",
2329 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002330 }
2331 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002332 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002333 }
2334 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002335 /* Mark that we are taking the process down. */
2336 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002337 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002338 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002339 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002340 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002341 } else {
2342 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2343 cleanup();
2344 return -1;
2345 }
2346 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002347 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002348 if (leader != tcp)
2349 droptcb(tcp);
2350 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002351 /* The leader will report to us as parent now,
2352 and then we'll get to the SIG==-1 case. */
2353 return 0;
2354 }
2355 }
2356
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002357 return 0;
2358}
2359#endif
2360
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002361#ifdef LINUX
2362static int
2363handle_ptrace_event(int status, struct tcb *tcp)
2364{
2365 if (status >> 16 == PTRACE_EVENT_VFORK ||
2366 status >> 16 == PTRACE_EVENT_CLONE ||
2367 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002368 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002369
2370 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2371 if (errno != ESRCH) {
2372 fprintf(stderr, "\
2373%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2374 progname);
2375 cleanup();
2376 exit(1);
2377 }
2378 return -1;
2379 }
2380 return handle_new_child(tcp, childpid, 0);
2381 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002382 if (status >> 16 == PTRACE_EVENT_EXEC) {
2383 if (debug)
2384 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2385 return 0;
2386 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002387 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2388 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002389 return 1;
2390}
2391#endif
2392
Roland McGratheb9e2e82009-06-02 16:49:22 -07002393static int
2394trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002395{
2396 int pid;
2397 int wait_errno;
2398 int status;
2399 struct tcb *tcp;
2400#ifdef LINUX
2401 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002402#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002403 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002404#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002405#endif /* LINUX */
2406
Roland McGratheb9e2e82009-06-02 16:49:22 -07002407 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002408 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002409 return 0;
2410 if (interactive)
2411 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002412#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002413#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002414 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002415 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002416 /* this kernel does not support __WALL */
2417 wait4_options &= ~__WALL;
2418 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002419 pid = wait4(-1, &status, wait4_options,
2420 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002421 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002422 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002423 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002424 pid = wait4(-1, &status, __WCLONE,
2425 cflag ? &ru : NULL);
2426 if (pid == -1) {
2427 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002428 "failed: %s\n", strerror(errno));
2429 }
2430 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002431#else
2432 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2433#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434#endif /* LINUX */
2435#ifdef SUNOS4
2436 pid = wait(&status);
2437#endif /* SUNOS4 */
2438 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002439 if (interactive)
2440 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002441
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002443 switch (wait_errno) {
2444 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002446 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447 /*
2448 * We would like to verify this case
2449 * but sometimes a race in Solbourne's
2450 * version of SunOS sometimes reports
2451 * ECHILD before sending us SIGCHILD.
2452 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002453 return 0;
2454 default:
2455 errno = wait_errno;
2456 perror("strace: wait");
2457 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002458 }
2459 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002460 if (pid == popen_pid) {
2461 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002462 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002463 continue;
2464 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002465 if (debug)
2466 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2467
2468 /* Look up `pid' in our table. */
2469 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002470#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002471 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002472 /* This is needed to go with the CLONE_PTRACE
2473 changes in process.c/util.c: we might see
2474 the child's initial trap before we see the
2475 parent return from the clone syscall.
2476 Leave the child suspended until the parent
2477 returns from its system call. Only then
2478 will we have the association of parent and
2479 child so that we know how to do clearbpt
2480 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002481 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002482 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002483 if (!qflag)
2484 fprintf(stderr, "\
2485Process %d attached (waiting for parent)\n",
2486 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002487 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002488 else
2489 /* This can happen if a clone call used
2490 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002491#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002492 {
2493 fprintf(stderr, "unknown pid: %u\n", pid);
2494 if (WIFSTOPPED(status))
2495 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2496 exit(1);
2497 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002498 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002499 /* set current output file */
2500 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002501 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002502 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002503#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002504 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2505 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002506#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002507 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002508
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002509 if (tcp->flags & TCB_SUSPENDED) {
2510 /*
2511 * Apparently, doing any ptrace() call on a stopped
2512 * process, provokes the kernel to report the process
2513 * status again on a subsequent wait(), even if the
2514 * process has not been actually restarted.
2515 * Since we have inspected the arguments of suspended
2516 * processes we end up here testing for this case.
2517 */
2518 continue;
2519 }
2520 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002521 if (pid == strace_child)
2522 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002523 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002524 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2525 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002526 tprintf("+++ killed by %s %s+++",
2527 signame(WTERMSIG(status)),
2528#ifdef WCOREDUMP
2529 WCOREDUMP(status) ? "(core dumped) " :
2530#endif
2531 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002532 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002534#ifdef TCB_GROUP_EXITING
2535 handle_group_exit(tcp, -1);
2536#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002538#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 continue;
2540 }
2541 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002542 if (pid == strace_child)
2543 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002545 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2546 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002547#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002548 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002549 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002550#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002551 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002552 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002553 "PANIC: attached pid %u exited with %d\n",
2554 pid, WEXITSTATUS(status));
2555 }
Roland McGrath0a396902003-06-10 03:05:53 +00002556 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002557 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002558 tprintf(" <unfinished ... exit status %d>\n",
2559 WEXITSTATUS(status));
2560 tcp_last = NULL;
2561 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002562#ifdef TCB_GROUP_EXITING
2563 handle_group_exit(tcp, -1);
2564#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002565 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002566#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002567 continue;
2568 }
2569 if (!WIFSTOPPED(status)) {
2570 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2571 droptcb(tcp);
2572 continue;
2573 }
2574 if (debug)
2575 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002576 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002578 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002579 if (handle_ptrace_event(status, tcp) != 1)
2580 goto tracing;
2581 }
2582
Roland McGrath02203312007-06-11 22:06:31 +00002583 /*
2584 * Interestingly, the process may stop
2585 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002586 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002587 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002588 * A no-MMU vforked child won't send up a signal,
2589 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002590 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002591 if ((tcp->flags & TCB_STARTUP) &&
2592 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002593 /*
2594 * This flag is there to keep us in sync.
2595 * Next time this process stops it should
2596 * really be entering a system call.
2597 */
2598 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002599 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002600 /*
2601 * One example is a breakpoint inherited from
2602 * parent through fork ().
2603 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002604 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2605 droptcb(tcp);
2606 cleanup();
2607 return -1;
2608 }
2609 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002610#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002611 /* If options were not set for this tracee yet */
2612 if (tcp->parent == NULL) {
2613 if (ptrace_setoptions) {
2614 if (debug)
2615 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2616 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2617 if (errno != ESRCH) {
2618 /* Should never happen, really */
2619 perror_msg_and_die("PTRACE_SETOPTIONS");
2620 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002621 }
2622 }
2623 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002624#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625 goto tracing;
2626 }
2627
Denys Vlasenko75422762011-05-27 14:36:01 +02002628 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629 if (WSTOPSIG(status) == SIGSTOP &&
2630 (tcp->flags & TCB_SIGTRAPPED)) {
2631 /*
2632 * Trapped attempt to block SIGTRAP
2633 * Hope we are back in control now.
2634 */
2635 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002636 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002637 cleanup();
2638 return -1;
2639 }
2640 continue;
2641 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002642 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002644 siginfo_t si;
2645#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002646 long pc = 0;
2647 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002648
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002649 upeek(tcp, PT_CR_IPSR, &psr);
2650 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002651
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002652# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002653 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002654# define PC_FORMAT_STR " @ %lx"
2655# define PC_FORMAT_ARG pc
2656#else
2657# define PC_FORMAT_STR "%s"
2658# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002659#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002660 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002661 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2662 tprintf("--- ");
2663 printsiginfo(&si, verbose(tcp));
2664 tprintf(" (%s)" PC_FORMAT_STR " ---",
2665 strsignal(WSTOPSIG(status)),
2666 PC_FORMAT_ARG);
2667 } else
2668 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2669 strsignal(WSTOPSIG(status)),
2670 signame(WSTOPSIG(status)),
2671 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002672 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002673 }
Roland McGrath05690952004-10-20 01:00:27 +00002674 if (((tcp->flags & TCB_ATTACHED) ||
2675 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002676 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002677#ifdef TCB_GROUP_EXITING
2678 handle_group_exit(tcp, WSTOPSIG(status));
2679#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002680 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002681#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002682 continue;
2683 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002684 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002685 cleanup();
2686 return -1;
2687 }
2688 tcp->flags &= ~TCB_SUSPENDED;
2689 continue;
2690 }
Roland McGrath02203312007-06-11 22:06:31 +00002691 /* we handled the STATUS, we are permitted to interrupt now. */
2692 if (interrupted)
2693 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002694 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2695 /* ptrace() failed in trace_syscall() with ESRCH.
2696 * Likely a result of process disappearing mid-flight.
2697 * Observed case: exit_group() terminating
2698 * all processes in thread group. In this case, threads
2699 * "disappear" in an unpredictable moment without any
2700 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002701 */
2702 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002703 if (tcp_last) {
2704 /* Do we have dangling line "syscall(param, param"?
2705 * Finish the line then. We cannot
2706 */
2707 tcp_last->flags |= TCB_REPRINT;
2708 tprintf(" <unfinished ...>");
2709 printtrailer();
2710 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002712 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002713 ptrace(PTRACE_KILL,
2714 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002715 droptcb(tcp);
2716 }
2717 continue;
2718 }
2719 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002720#ifdef TCB_GROUP_EXITING
2721 if (tcp->flags & TCB_GROUP_EXITING) {
2722 if (handle_group_exit(tcp, 0) < 0)
2723 return -1;
2724 continue;
2725 }
2726#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002727 if (tcp->flags & TCB_ATTACHED)
2728 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002729 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002730 cleanup();
2731 return -1;
2732 }
2733 continue;
2734 }
2735 if (tcp->flags & TCB_SUSPENDED) {
2736 if (!qflag)
2737 fprintf(stderr, "Process %u suspended\n", pid);
2738 continue;
2739 }
2740 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002741 /* Remember current print column before continuing. */
2742 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002743 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002744 cleanup();
2745 return -1;
2746 }
2747 }
2748 return 0;
2749}
2750
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002751#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002752
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002753#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002754
2755void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002756tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002757{
2758 va_list args;
2759
Andreas Schwabe5355de2009-10-27 16:56:43 +01002760 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002761 if (outf) {
2762 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002763 if (n < 0) {
2764 if (outf != stderr)
2765 perror(outfname == NULL
2766 ? "<writing to pipe>" : outfname);
2767 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002768 curcol += n;
2769 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002770 va_end(args);
2771 return;
2772}
2773
2774void
Denys Vlasenko12014262011-05-30 14:00:14 +02002775printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002776{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002777 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002778 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002779 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002780 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002781 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002782 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002783 tprintf("= ? <unavailable>\n");
2784 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002785 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002786 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002787 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002788 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002789 }
2790 curcol = 0;
2791 if ((followfork == 1 || pflag_seen > 1) && outfname)
2792 tprintf("%-5d ", tcp->pid);
2793 else if (nprocs > 1 && !outfname)
2794 tprintf("[pid %5u] ", tcp->pid);
2795 if (tflag) {
2796 char str[sizeof("HH:MM:SS")];
2797 struct timeval tv, dtv;
2798 static struct timeval otv;
2799
2800 gettimeofday(&tv, NULL);
2801 if (rflag) {
2802 if (otv.tv_sec == 0)
2803 otv = tv;
2804 tv_sub(&dtv, &tv, &otv);
2805 tprintf("%6ld.%06ld ",
2806 (long) dtv.tv_sec, (long) dtv.tv_usec);
2807 otv = tv;
2808 }
2809 else if (tflag > 2) {
2810 tprintf("%ld.%06ld ",
2811 (long) tv.tv_sec, (long) tv.tv_usec);
2812 }
2813 else {
2814 time_t local = tv.tv_sec;
2815 strftime(str, sizeof(str), "%T", localtime(&local));
2816 if (tflag > 1)
2817 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2818 else
2819 tprintf("%s ", str);
2820 }
2821 }
2822 if (iflag)
2823 printcall(tcp);
2824}
2825
2826void
Denys Vlasenko12014262011-05-30 14:00:14 +02002827tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002828{
2829 if (curcol < col)
2830 tprintf("%*s", col - curcol, "");
2831}
2832
2833void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002834printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002835{
2836 tprintf("\n");
2837 tcp_last = NULL;
2838}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002839
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002840#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002841
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002842int
2843mp_ioctl(int fd, int cmd, void *arg, int size)
2844{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002845 struct iovec iov[2];
2846 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002847
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002848 iov[0].iov_base = &cmd;
2849 iov[0].iov_len = sizeof cmd;
2850 if (arg) {
2851 ++n;
2852 iov[1].iov_base = arg;
2853 iov[1].iov_len = size;
2854 }
Roland McGrath553a6092002-12-16 20:40:39 +00002855
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002856 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002857}
2858
2859#endif