blob: bfa9a0d1c0369e5a5b3ab89261cc800128c96544 [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>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020052# if defined __NR_tkill
53# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# else
55 /* kill() may choose arbitrarily the target task of the process group
56 while we later wait on a that specific TID. PID process waits become
57 TID task specific waits for a process under ptrace(2). */
58# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020059# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000060# endif
61#endif
62
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000063#if defined(IA64) && defined(LINUX)
64# include <asm/ptrace_offsets.h>
65#endif
66
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000067#ifdef USE_PROCFS
68#include <poll.h>
69#endif
70
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071#ifdef SVR4
72#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000073#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000074#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000075#include <sys/uio.h>
76#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000078#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000079extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000080extern int optind;
81extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000082
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083
Roland McGrath41c48222008-07-18 00:25:10 +000084int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020085unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020086/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020087static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000088int dtime = 0, xflag = 0, qflag = 0;
89cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000090static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000105/* Sometimes we want to print only succeeding syscalls. */
106int not_failing_only = 0;
107
Grant Edwards8a082772011-04-07 20:25:40 +0000108/* Show path associated with fd arguments */
109int show_fd_path = 0;
110
111/* are we filtering traces based on paths? */
112int tracing_paths = 0;
113
Dmitry V. Levina6809652008-11-10 17:14:58 +0000114static int exit_code = 0;
115static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200116static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700117
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000118static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200119static uid_t run_uid;
120static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
122int acolumn = DEFAULT_ACOLUMN;
123int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000124static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200125static FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100126static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200128static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200129static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
Andreas Schwabe5355de2009-10-27 16:56:43 +0100131static int detach(struct tcb *tcp, int sig);
132static int trace(void);
133static void cleanup(void);
134static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135static sigset_t empty_set, blocked_set;
136
137#ifdef HAVE_SIG_ATOMIC_T
138static volatile sig_atomic_t interrupted;
139#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141#endif /* !HAVE_SIG_ATOMIC_T */
142
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000143#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144
Andreas Schwabe5355de2009-10-27 16:56:43 +0100145static struct tcb *pfd2tcb(int pfd);
146static void reaper(int sig);
147static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000148static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149
150#ifndef HAVE_POLLABLE_PROCFS
151
Andreas Schwabe5355de2009-10-27 16:56:43 +0100152static void proc_poll_open(void);
153static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
155struct proc_pollfd {
156 int fd;
157 int revents;
158 int pid;
159};
160
161static int poller_pid;
162static int proc_poll_pipe[2] = { -1, -1 };
163
164#endif /* !HAVE_POLLABLE_PROCFS */
165
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000166#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000167#define POLLWANT POLLWRNORM
168#else
169#define POLLWANT POLLPRI
170#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000171#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172
173static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200174usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175{
176 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000177usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000178 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000179 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200180 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000181 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200183-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-f -- follow forks, -ff -- with output into separate files\n\
185-F -- attempt to follow vforks, -h -- print help message\n\
186-i -- print instruction pointer at time of syscall\n\
187-q -- suppress messages about attaching, detaching, etc.\n\
188-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
189-T -- print time spent in each syscall, -V -- print version\n\
190-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
191-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000192-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193-a column -- alignment COLUMN for printing syscall results (default %d)\n\
194-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
195 options: trace, abbrev, verbose, raw, signal, read, or write\n\
196-o file -- send trace output to FILE instead of stderr\n\
197-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
198-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000199-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
201-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
202-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000203-E var=val -- put var=val in the environment for command\n\
204-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000205-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000206" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000207-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208 */
209, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210 exit(exitval);
211}
212
Denys Vlasenko75422762011-05-27 14:36:01 +0200213static void die(void) __attribute__ ((noreturn));
214static void die(void)
215{
216 if (strace_tracer_pid == getpid()) {
217 cflag = 0;
218 cleanup();
219 }
220 exit(1);
221}
222
223static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200224{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000225 fflush(NULL);
226 fprintf(stderr, "%s: ", progname);
227 vfprintf(stderr, fmt, p);
228 if (err_no)
229 fprintf(stderr, ": %s\n", strerror(err_no));
230 else
231 putc('\n', stderr);
232 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200233}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200234
Denys Vlasenko75422762011-05-27 14:36:01 +0200235void error_msg(const char *fmt, ...)
236{
237 va_list p;
238 va_start(p, fmt);
239 verror_msg(0, fmt, p);
240 va_end(p);
241}
242
243void error_msg_and_die(const char *fmt, ...)
244{
245 va_list p;
246 va_start(p, fmt);
247 verror_msg(0, fmt, p);
248 die();
249}
250
251void perror_msg(const char *fmt, ...)
252{
253 va_list p;
254 va_start(p, fmt);
255 verror_msg(errno, fmt, p);
256 va_end(p);
257}
258
259void perror_msg_and_die(const char *fmt, ...)
260{
261 va_list p;
262 va_start(p, fmt);
263 verror_msg(errno, fmt, p);
264 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200265}
266
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000267#ifdef SVR4
268#ifdef MIPS
269void
270foobar()
271{
272}
273#endif /* MIPS */
274#endif /* SVR4 */
275
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400276/* Glue for systems without a MMU that cannot provide fork() */
277#ifdef HAVE_FORK
278# define strace_vforked 0
279#else
280# define strace_vforked 1
281# define fork() vfork()
282#endif
283
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200284static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000285set_cloexec_flag(int fd)
286{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200287 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000288
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200289 flags = fcntl(fd, F_GETFD);
290 if (flags < 0) {
291 /* Can happen only if fd is bad.
292 * Should never happen: if it does, we have a bug
293 * in the caller. Therefore we just abort
294 * instead of propagating the error.
295 */
296 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000297 }
298
299 newflags = flags | FD_CLOEXEC;
300 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200301 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000302
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200303 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000304}
305
306/*
307 * When strace is setuid executable, we have to swap uids
308 * before and after filesystem and process management operations.
309 */
310static void
311swap_uid(void)
312{
313#ifndef SVR4
314 int euid = geteuid(), uid = getuid();
315
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200316 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200317 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000318 }
319#endif
320}
321
Roland McGrath4bfa6262007-07-05 20:03:16 +0000322#if _LFS64_LARGEFILE
323# define fopen_for_output fopen64
324#else
325# define fopen_for_output fopen
326#endif
327
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000328static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200329strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330{
331 FILE *fp;
332
333 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200334 fp = fopen_for_output(path, "w");
335 if (!fp)
336 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000337 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200338 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000339 return fp;
340}
341
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200342static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343
344#ifndef _PATH_BSHELL
345# define _PATH_BSHELL "/bin/sh"
346#endif
347
348/*
349 * We cannot use standard popen(3) here because we have to distinguish
350 * popen child process from other processes we trace, and standard popen(3)
351 * does not export its child's pid.
352 */
353static FILE *
354strace_popen(const char *command)
355{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200356 FILE *fp;
357 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000358
359 swap_uid();
360 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200361 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200363 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200365 popen_pid = vfork();
366 if (popen_pid == -1)
367 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000368
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200369 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370 /* child */
371 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200372 if (fds[0] != 0) {
373 if (dup2(fds[0], 0))
374 perror_msg_and_die("dup2");
375 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376 }
377 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200378 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000379 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200380
381 /* parent */
382 close(fds[0]);
383 swap_uid();
384 fp = fdopen(fds[1], "w");
385 if (!fp)
386 error_msg_and_die("Out of memory");
387 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388}
389
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200390static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391newoutf(struct tcb *tcp)
392{
393 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000394 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000395 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200396 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000398}
399
Roland McGrath02203312007-06-11 22:06:31 +0000400static void
401startup_attach(void)
402{
403 int tcbi;
404 struct tcb *tcp;
405
406 /*
407 * Block user interruptions as we would leave the traced
408 * process stopped (process state T) if we would terminate in
409 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200410 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000411 */
412 if (interactive)
413 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
414
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000415 if (daemonized_tracer) {
416 pid_t pid = fork();
417 if (pid < 0) {
418 _exit(1);
419 }
420 if (pid) { /* parent */
421 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200422 * Wait for grandchild to attach to straced process
423 * (grandparent). Grandchild SIGKILLs us after it attached.
424 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000425 * it proceeds to exec the straced program.
426 */
427 pause();
428 _exit(0); /* paranoia */
429 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200430 /* grandchild */
431 /* We will be the tracer process. Remember our new pid: */
432 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000433 }
434
Roland McGrath02203312007-06-11 22:06:31 +0000435 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
436 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200437
Roland McGrath02203312007-06-11 22:06:31 +0000438 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
439 continue;
440#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200441 if (tcp->flags & TCB_ATTACH_DONE)
Roland McGrath02203312007-06-11 22:06:31 +0000442 continue;
443#endif
444 /* Reinitialize the output since it may have changed. */
445 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200446 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000447
448#ifdef USE_PROCFS
449 if (proc_open(tcp, 1) < 0) {
450 fprintf(stderr, "trouble opening proc file\n");
451 droptcb(tcp);
452 continue;
453 }
454#else /* !USE_PROCFS */
455# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000456 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000457 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000458 DIR *dir;
459
460 sprintf(procdir, "/proc/%d/task", tcp->pid);
461 dir = opendir(procdir);
462 if (dir != NULL) {
463 unsigned int ntid = 0, nerr = 0;
464 struct dirent *de;
465 int tid;
466 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000467 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000468 continue;
469 tid = atoi(de->d_name);
470 if (tid <= 0)
471 continue;
472 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200473 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000474 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200475 if (debug)
476 fprintf(stderr, "attach to pid %d failed\n", tid);
477 }
478 else {
479 if (debug)
480 fprintf(stderr, "attach to pid %d succeeded\n", tid);
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200481 if (tid != tcp->pid) {
482 struct tcb *new_tcp = alloctcb(tid);
483 new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200484 }
Roland McGrath02203312007-06-11 22:06:31 +0000485 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000486 if (interactive) {
487 sigprocmask(SIG_SETMASK, &empty_set, NULL);
488 if (interrupted)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200489 goto ret;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000490 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",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200504 tcp->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) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200509# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000510 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
511 perror("attach: ptrace(PTRACE_ATTACH, ...)");
512 droptcb(tcp);
513 continue;
514 }
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200515 if (debug)
516 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000517
518 if (daemonized_tracer) {
519 /*
520 * It is our grandparent we trace, not a -p PID.
521 * Don't want to just detach on exit, so...
522 */
523 tcp->flags &= ~TCB_ATTACHED;
524 /*
525 * Make parent go away.
526 * Also makes grandparent's wait() unblock.
527 */
528 kill(getppid(), SIGKILL);
529 }
530
Roland McGrath02203312007-06-11 22:06:31 +0000531#endif /* !USE_PROCFS */
532 if (!qflag)
533 fprintf(stderr,
534 "Process %u attached - interrupt to quit\n",
535 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200536 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000537
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200538 ret:
539#ifdef LINUX
540 /* TCB_ATTACH_DONE flag is used only in this function */
541 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
542 tcp = tcbtab[tcbi];
543 tcp->flags &= ~TCB_ATTACH_DONE;
544 }
545#endif
546
Roland McGrath02203312007-06-11 22:06:31 +0000547 if (interactive)
548 sigprocmask(SIG_SETMASK, &empty_set, NULL);
549}
550
551static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200552startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000553{
554 struct stat statbuf;
555 const char *filename;
556 char pathname[MAXPATHLEN];
557 int pid = 0;
558 struct tcb *tcp;
559
560 filename = argv[0];
561 if (strchr(filename, '/')) {
562 if (strlen(filename) > sizeof pathname - 1) {
563 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200564 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000565 }
566 strcpy(pathname, filename);
567 }
568#ifdef USE_DEBUGGING_EXEC
569 /*
570 * Debuggers customarily check the current directory
571 * first regardless of the path but doing that gives
572 * security geeks a panic attack.
573 */
574 else if (stat(filename, &statbuf) == 0)
575 strcpy(pathname, filename);
576#endif /* USE_DEBUGGING_EXEC */
577 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000578 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000579 int m, n, len;
580
581 for (path = getenv("PATH"); path && *path; path += m) {
582 if (strchr(path, ':')) {
583 n = strchr(path, ':') - path;
584 m = n + 1;
585 }
586 else
587 m = n = strlen(path);
588 if (n == 0) {
589 if (!getcwd(pathname, MAXPATHLEN))
590 continue;
591 len = strlen(pathname);
592 }
593 else if (n > sizeof pathname - 1)
594 continue;
595 else {
596 strncpy(pathname, path, n);
597 len = n;
598 }
599 if (len && pathname[len - 1] != '/')
600 pathname[len++] = '/';
601 strcpy(pathname + len, filename);
602 if (stat(pathname, &statbuf) == 0 &&
603 /* Accept only regular files
604 with some execute bits set.
605 XXX not perfect, might still fail */
606 S_ISREG(statbuf.st_mode) &&
607 (statbuf.st_mode & 0111))
608 break;
609 }
610 }
611 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200612 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000613 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000614 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000615 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200616 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000617 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200618 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
619 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000620 ) {
621 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000622#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200623 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000624#ifdef MIPS
625 /* Kludge for SGI, see proc_open for details. */
626 sa.sa_handler = foobar;
627 sa.sa_flags = 0;
628 sigemptyset(&sa.sa_mask);
629 sigaction(SIGINT, &sa, NULL);
630#endif /* MIPS */
631#ifndef FREEBSD
632 pause();
633#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000634 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000635#endif /* FREEBSD */
636#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200637 if (outf != stderr)
638 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000639
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000640 if (!daemonized_tracer) {
641 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200642 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000643 }
644 if (debug)
645 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000646 }
Roland McGrath02203312007-06-11 22:06:31 +0000647
648 if (username != NULL || geteuid() == 0) {
649 uid_t run_euid = run_uid;
650 gid_t run_egid = run_gid;
651
652 if (statbuf.st_mode & S_ISUID)
653 run_euid = statbuf.st_uid;
654 if (statbuf.st_mode & S_ISGID)
655 run_egid = statbuf.st_gid;
656
657 /*
658 * It is important to set groups before we
659 * lose privileges on setuid.
660 */
661 if (username != NULL) {
662 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200663 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000664 }
665 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200666 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000667 }
668 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200669 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000670 }
671 }
672 }
673 else
674 setreuid(run_uid, run_uid);
675
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 if (!daemonized_tracer) {
677 /*
678 * Induce an immediate stop so that the parent
679 * will resume us with PTRACE_SYSCALL and display
680 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400681 * Unless of course we're on a no-MMU system where
682 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400684 if (!strace_vforked)
685 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000686 } else {
687 struct sigaction sv_sigchld;
688 sigaction(SIGCHLD, NULL, &sv_sigchld);
689 /*
690 * Make sure it is not SIG_IGN, otherwise wait
691 * will not block.
692 */
693 signal(SIGCHLD, SIG_DFL);
694 /*
695 * Wait for grandchild to attach to us.
696 * It kills child after that, and wait() unblocks.
697 */
698 alarm(3);
699 wait(NULL);
700 alarm(0);
701 sigaction(SIGCHLD, &sv_sigchld, NULL);
702 }
Roland McGrath02203312007-06-11 22:06:31 +0000703#endif /* !USE_PROCFS */
704
705 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200706 perror_msg_and_die("exec");
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) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200720 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000721 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000723}
724
Wang Chaob13c0de2010-11-12 17:25:19 +0800725#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000726static void kill_save_errno(pid_t pid, int sig)
727{
728 int saved_errno = errno;
729
730 (void) kill(pid, sig);
731 errno = saved_errno;
732}
733
Wang Chaob13c0de2010-11-12 17:25:19 +0800734/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000735 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800736 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000737 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800738 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000739static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200740test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800741{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000742 int pid, expected_grandchild = 0, found_grandchild = 0;
743 const unsigned int test_options = PTRACE_O_TRACECLONE |
744 PTRACE_O_TRACEFORK |
745 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800746
747 if ((pid = fork()) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000748 perror_msg_and_die("fork");
Wang Chaob13c0de2010-11-12 17:25:19 +0800749 else if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000750 pid = getpid();
751 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
752 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
753 __func__);
754 kill(pid, SIGSTOP);
755 if (fork() < 0)
756 perror_msg_and_die("fork");
757 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800758 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000759
760 while (1) {
761 int status, tracee_pid;
762
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000763 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000764 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000765 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000766 if (errno == EINTR)
767 continue;
768 else if (errno == ECHILD)
769 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000770 kill_save_errno(pid, SIGKILL);
771 perror_msg_and_die("%s: unexpected wait result %d",
772 __func__, tracee_pid);
773 }
774 if (WIFEXITED(status)) {
775 if (WEXITSTATUS(status)) {
776 if (tracee_pid != pid)
777 kill_save_errno(pid, SIGKILL);
778 error_msg_and_die("%s: unexpected exit status %u",
779 __func__, WEXITSTATUS(status));
780 }
781 continue;
782 }
783 if (WIFSIGNALED(status)) {
784 if (tracee_pid != pid)
785 kill_save_errno(pid, SIGKILL);
786 error_msg_and_die("%s: unexpected signal %u",
787 __func__, WTERMSIG(status));
788 }
789 if (!WIFSTOPPED(status)) {
790 if (tracee_pid != pid)
791 kill_save_errno(tracee_pid, SIGKILL);
792 kill(pid, SIGKILL);
793 error_msg_and_die("%s: unexpected wait status %x",
794 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000795 }
796 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000797 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000798 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
799 kill_save_errno(tracee_pid, SIGKILL);
800 kill_save_errno(pid, SIGKILL);
801 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800802 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000803 continue;
804 }
805 switch (WSTOPSIG(status)) {
806 case SIGSTOP:
807 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
808 && errno != EINVAL && errno != EIO)
809 perror_msg("PTRACE_SETOPTIONS");
810 break;
811 case SIGTRAP:
812 if (status >> 16 == PTRACE_EVENT_FORK) {
813 long msg = 0;
814
815 if (ptrace(PTRACE_GETEVENTMSG, pid,
816 NULL, (long) &msg) == 0)
817 expected_grandchild = msg;
818 }
819 break;
820 }
821 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
822 kill_save_errno(pid, SIGKILL);
823 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800824 }
825 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000826 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200827 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000828 if (debug)
829 fprintf(stderr, "ptrace_setoptions = %#x\n",
830 ptrace_setoptions);
831 return;
832 }
833 error_msg("Test for PTRACE_O_TRACECLONE failed, "
834 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800835}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200836
837/*
838 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
839 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
840 * and then see whether it will stop with (SIGTRAP | 0x80).
841 *
842 * Use of this option enables correct handling of user-generated SIGTRAPs,
843 * and SIGTRAPs generated by special instructions such as int3 on x86:
844 * _start: .globl _start
845 * int3
846 * movl $42, %ebx
847 * movl $1, %eax
848 * int $0x80
849 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
850 */
851static void
852test_ptrace_setoptions_for_all(void)
853{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000854 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
855 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200856 int pid;
857 int it_worked = 0;
858
859 pid = fork();
860 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200861 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200862
863 if (pid == 0) {
864 pid = getpid();
865 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200866 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000867 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
868 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200869 kill(pid, SIGSTOP);
870 _exit(0); /* parent should see entry into this syscall */
871 }
872
873 while (1) {
874 int status, tracee_pid;
875
876 errno = 0;
877 tracee_pid = wait(&status);
878 if (tracee_pid <= 0) {
879 if (errno == EINTR)
880 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000881 kill_save_errno(pid, SIGKILL);
882 perror_msg_and_die("%s: unexpected wait result %d",
883 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200884 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200885 if (WIFEXITED(status)) {
886 if (WEXITSTATUS(status) == 0)
887 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000888 error_msg_and_die("%s: unexpected exit status %u",
889 __func__, WEXITSTATUS(status));
890 }
891 if (WIFSIGNALED(status)) {
892 error_msg_and_die("%s: unexpected signal %u",
893 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200894 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200895 if (!WIFSTOPPED(status)) {
896 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000897 error_msg_and_die("%s: unexpected wait status %x",
898 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200899 }
900 if (WSTOPSIG(status) == SIGSTOP) {
901 /*
902 * We don't check "options aren't accepted" error.
903 * If it happens, we'll never get (SIGTRAP | 0x80),
904 * and thus will decide to not use the option.
905 * IOW: the outcome of the test will be correct.
906 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000907 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
908 && errno != EINVAL && errno != EIO)
909 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200910 }
911 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
912 it_worked = 1;
913 }
914 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000915 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200916 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200917 }
918 }
919
920 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200921 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200922 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200923 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200924 fprintf(stderr, "ptrace_setoptions = %#x\n",
925 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200926 return;
927 }
928
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000929 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
930 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200931}
Wang Chaob13c0de2010-11-12 17:25:19 +0800932#endif
933
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000935main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000937 struct tcb *tcp;
938 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000939 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 struct sigaction sa;
941
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000942 progname = argv[0] ? argv[0] : "strace";
943
Denys Vlasenko75422762011-05-27 14:36:01 +0200944 strace_tracer_pid = getpid();
945
Roland McGrathee9d4352002-12-18 04:16:10 +0000946 /* Allocate the initial tcbtab. */
947 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200948 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200949 if (tcbtab == NULL)
950 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200951 tcp = calloc(tcbtabsize, sizeof(*tcp));
952 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200953 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200954 for (c = 0; c < tcbtabsize; c++)
955 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000956
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 outf = stderr;
958 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000959 set_sortby(DEFAULT_SORTBY);
960 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000961 qualify("trace=all");
962 qualify("abbrev=all");
963 qualify("verbose=all");
964 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000966 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000967#ifndef USE_PROCFS
968 "D"
969#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000970 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 switch (c) {
972 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000973 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200974 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000975 }
976 cflag = CFLAG_ONLY_STATS;
977 break;
978 case 'C':
979 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200980 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000981 }
982 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 break;
984 case 'd':
985 debug++;
986 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000987#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000988 case 'D':
989 daemonized_tracer = 1;
990 break;
991#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000992 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000993 optF = 1;
994 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995 case 'f':
996 followfork++;
997 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 case 'h':
999 usage(stdout, 0);
1000 break;
1001 case 'i':
1002 iflag++;
1003 break;
1004 case 'q':
1005 qflag++;
1006 break;
1007 case 'r':
1008 rflag++;
1009 tflag++;
1010 break;
1011 case 't':
1012 tflag++;
1013 break;
1014 case 'T':
1015 dtime++;
1016 break;
1017 case 'x':
1018 xflag++;
1019 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001020 case 'y':
1021 show_fd_path = 1;
1022 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 case 'v':
1024 qualify("abbrev=none");
1025 break;
1026 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001027 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 exit(0);
1029 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001030 case 'z':
1031 not_failing_only = 1;
1032 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 case 'a':
1034 acolumn = atoi(optarg);
1035 break;
1036 case 'e':
1037 qualify(optarg);
1038 break;
1039 case 'o':
1040 outfname = strdup(optarg);
1041 break;
1042 case 'O':
1043 set_overhead(atoi(optarg));
1044 break;
1045 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +00001046 if ((pid = atoi(optarg)) <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001047 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 break;
1049 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001050 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001051 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 break;
1053 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001054 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 tcp->flags |= TCB_ATTACHED;
1056 pflag_seen++;
1057 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001058 case 'P':
1059 tracing_paths = 1;
1060 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001061 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001062 }
1063 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 case 's':
1065 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001066 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001067 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001068 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 break;
1070 case 'S':
1071 set_sortby(optarg);
1072 break;
1073 case 'u':
1074 username = strdup(optarg);
1075 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001076 case 'E':
1077 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001078 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001079 }
1080 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081 default:
1082 usage(stderr, 1);
1083 break;
1084 }
1085 }
1086
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001087 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001088 usage(stderr, 1);
1089
Wang Chaod322a4b2010-08-05 14:30:11 +08001090 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001091 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001092 }
1093
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001094 if (!followfork)
1095 followfork = optF;
1096
Roland McGrathcb9def62006-04-25 07:48:03 +00001097 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001098 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001099 }
1100
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 /* See if they want to run as another user. */
1102 if (username != NULL) {
1103 struct passwd *pent;
1104
1105 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001106 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 }
1108 if ((pent = getpwnam(username)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001109 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 }
1111 run_uid = pent->pw_uid;
1112 run_gid = pent->pw_gid;
1113 }
1114 else {
1115 run_uid = getuid();
1116 run_gid = getgid();
1117 }
1118
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001119#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001120 if (followfork)
1121 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001122 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001123#endif
1124
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001125 /* Check if they want to redirect the output. */
1126 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001127 /* See if they want to pipe the output. */
1128 if (outfname[0] == '|' || outfname[0] == '!') {
1129 /*
1130 * We can't do the <outfname>.PID funny business
1131 * when using popen, so prohibit it.
1132 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001133 if (followfork > 1)
1134 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1135 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001136 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001137 else if (followfork <= 1)
1138 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 }
1140
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001141 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1142 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001144 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001145 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001148 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001149
Roland McGrath54cc1c82007-11-03 23:34:11 +00001150 /* Valid states here:
1151 optind < argc pflag_seen outfname interactive
1152 1 0 0 1
1153 0 1 0 1
1154 1 0 1 0
1155 0 1 1 1
1156 */
1157
1158 /* STARTUP_CHILD must be called before the signal handlers get
1159 installed below as they are inherited into the spawned process.
1160 Also we do not need to be protected by them as during interruption
1161 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1162 if (!pflag_seen)
1163 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 sigemptyset(&empty_set);
1166 sigemptyset(&blocked_set);
1167 sa.sa_handler = SIG_IGN;
1168 sigemptyset(&sa.sa_mask);
1169 sa.sa_flags = 0;
1170 sigaction(SIGTTOU, &sa, NULL);
1171 sigaction(SIGTTIN, &sa, NULL);
1172 if (interactive) {
1173 sigaddset(&blocked_set, SIGHUP);
1174 sigaddset(&blocked_set, SIGINT);
1175 sigaddset(&blocked_set, SIGQUIT);
1176 sigaddset(&blocked_set, SIGPIPE);
1177 sigaddset(&blocked_set, SIGTERM);
1178 sa.sa_handler = interrupt;
1179#ifdef SUNOS4
1180 /* POSIX signals on sunos4.1 are a little broken. */
1181 sa.sa_flags = SA_INTERRUPT;
1182#endif /* SUNOS4 */
1183 }
1184 sigaction(SIGHUP, &sa, NULL);
1185 sigaction(SIGINT, &sa, NULL);
1186 sigaction(SIGQUIT, &sa, NULL);
1187 sigaction(SIGPIPE, &sa, NULL);
1188 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001189#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 sa.sa_handler = reaper;
1191 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001192#else
1193 /* Make sure SIGCHLD has the default action so that waitpid
1194 definitely works without losing track of children. The user
1195 should not have given us a bogus state to inherit, but he might
1196 have. Arguably we should detect SIG_IGN here and pass it on
1197 to children, but probably noone really needs that. */
1198 sa.sa_handler = SIG_DFL;
1199 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001200#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001202 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001203 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001204
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 if (trace() < 0)
1206 exit(1);
1207 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001208 fflush(NULL);
1209 if (exit_code > 0xff) {
1210 /* Child was killed by a signal, mimic that. */
1211 exit_code &= 0xff;
1212 signal(exit_code, SIG_DFL);
1213 raise(exit_code);
1214 /* Paranoia - what if this signal is not fatal?
1215 Exit with 128 + signo then. */
1216 exit_code += 128;
1217 }
1218 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219}
1220
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001221static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001222expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001223{
1224 /* Allocate some more TCBs and expand the table.
1225 We don't want to relocate the TCBs because our
1226 callers have pointers and it would be a pain.
1227 So tcbtab is a table of pointers. Since we never
1228 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001229 int i = tcbtabsize;
1230 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1231 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1232 if (newtab == NULL || newtcbs == NULL)
1233 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001234 tcbtabsize *= 2;
1235 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001236 while (i < tcbtabsize)
1237 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001238}
1239
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001240struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001241alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242{
1243 int i;
1244 struct tcb *tcp;
1245
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001246 if (nprocs == tcbtabsize)
1247 expand_tcbtab();
1248
Roland McGrathee9d4352002-12-18 04:16:10 +00001249 for (i = 0; i < tcbtabsize; i++) {
1250 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001252 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254 tcp->flags = TCB_INUSE | TCB_STARTUP;
1255 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256 tcp->pfd = -1;
1257 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001258 if (debug)
1259 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001260 if (command_options_parsed)
1261 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 return tcp;
1263 }
1264 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001265 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266}
1267
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001268#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001270proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271{
1272 char proc[32];
1273 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001274#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001275 int i;
1276 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001277 sigset_t signals;
1278 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001279#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280#ifndef HAVE_POLLABLE_PROCFS
1281 static int last_pfd;
1282#endif
1283
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001284#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001285 /* Open the process pseudo-files in /proc. */
1286 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1287 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288 perror("strace: open(\"/proc/...\", ...)");
1289 return -1;
1290 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001291 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001292 sprintf(proc, "/proc/%d/status", tcp->pid);
1293 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1294 perror("strace: open(\"/proc/...\", ...)");
1295 return -1;
1296 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001297 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001298 sprintf(proc, "/proc/%d/as", tcp->pid);
1299 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1300 perror("strace: open(\"/proc/...\", ...)");
1301 return -1;
1302 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001303 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001304#else
1305 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001306#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001307 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001308 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001309#else /* FREEBSD */
1310 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001311 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001312#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001313 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001314 perror("strace: open(\"/proc/...\", ...)");
1315 return -1;
1316 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001317 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001318#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001319#ifdef FREEBSD
1320 sprintf(proc, "/proc/%d/regs", tcp->pid);
1321 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1322 perror("strace: open(\"/proc/.../regs\", ...)");
1323 return -1;
1324 }
1325 if (cflag) {
1326 sprintf(proc, "/proc/%d/status", tcp->pid);
1327 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1328 perror("strace: open(\"/proc/.../status\", ...)");
1329 return -1;
1330 }
1331 } else
1332 tcp->pfd_status = -1;
1333#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001334 rebuild_pollv();
1335 if (!attaching) {
1336 /*
1337 * Wait for the child to pause. Because of a race
1338 * condition we have to poll for the event.
1339 */
1340 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001341 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001342 perror("strace: PIOCSTATUS");
1343 return -1;
1344 }
1345 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001346 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001347 }
1348 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001349#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001350 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001351 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001352 perror("strace: PIOCSTOP");
1353 return -1;
1354 }
Roland McGrath553a6092002-12-16 20:40:39 +00001355#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356#ifdef PIOCSET
1357 /* Set Run-on-Last-Close. */
1358 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001359 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 perror("PIOCSET PR_RLC");
1361 return -1;
1362 }
1363 /* Set or Reset Inherit-on-Fork. */
1364 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001365 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001366 perror("PIOC{SET,RESET} PR_FORK");
1367 return -1;
1368 }
1369#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001370#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001371 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1372 perror("PIOCSRLC");
1373 return -1;
1374 }
1375 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1376 perror("PIOC{S,R}FORK");
1377 return -1;
1378 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001379#else /* FREEBSD */
1380 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1381 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1382 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001383 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001384 }
1385 arg &= ~PF_LINGER;
1386 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001387 perror("PIOCSFL");
1388 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001389 }
1390#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001392#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001393 /* Enable all syscall entries we care about. */
1394 premptyset(&syscalls);
1395 for (i = 1; i < MAX_QUALS; ++i) {
1396 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001397 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001398 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001399 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001400 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001401 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001402#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001403 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001404#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001405#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001406 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001407#endif
1408#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001409 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001410#endif
1411#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001412 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001413#endif
1414 }
1415 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416 perror("PIOCSENTRY");
1417 return -1;
1418 }
John Hughes19e49982001-10-19 08:59:12 +00001419 /* Enable the syscall exits. */
1420 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421 perror("PIOSEXIT");
1422 return -1;
1423 }
John Hughes19e49982001-10-19 08:59:12 +00001424 /* Enable signals we care about. */
1425 premptyset(&signals);
1426 for (i = 1; i < MAX_QUALS; ++i) {
1427 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001428 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001429 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001430 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001431 perror("PIOCSTRACE");
1432 return -1;
1433 }
John Hughes19e49982001-10-19 08:59:12 +00001434 /* Enable faults we care about */
1435 premptyset(&faults);
1436 for (i = 1; i < MAX_QUALS; ++i) {
1437 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001438 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001439 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001440 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441 perror("PIOCSFAULT");
1442 return -1;
1443 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001444#else /* FREEBSD */
1445 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001446 arg = S_SIG | S_SCE | S_SCX;
1447 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001448 perror("PIOCBIS");
1449 return -1;
1450 }
1451#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452 if (!attaching) {
1453#ifdef MIPS
1454 /*
1455 * The SGI PRSABORT doesn't work for pause() so
1456 * we send it a caught signal to wake it up.
1457 */
1458 kill(tcp->pid, SIGINT);
1459#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001460#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001462 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001463 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464 perror("PIOCRUN");
1465 return -1;
1466 }
Roland McGrath553a6092002-12-16 20:40:39 +00001467#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001468#endif /* !MIPS*/
1469#ifdef FREEBSD
1470 /* wake up the child if it received the SIGSTOP */
1471 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001472#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473 for (;;) {
1474 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001475 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 perror("PIOCWSTOP");
1477 return -1;
1478 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001479 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001480 tcp->flags &= ~TCB_INSYSCALL;
1481 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001482 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 break;
1484 }
1485 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001486#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001487 arg = 0;
1488 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001489#else /* FREEBSD */
1490 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001491#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 perror("PIOCRUN");
1493 return -1;
1494 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001495#ifdef FREEBSD
1496 /* handle the case where we "opened" the child before
1497 it did the kill -STOP */
1498 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1499 tcp->status.PR_WHAT == SIGSTOP)
1500 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001501#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001503#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001505#else /* FREEBSD */
1506 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001507 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001508 /* We are attaching to an already running process.
1509 * Try to figure out the state of the process in syscalls,
1510 * to handle the first event well.
1511 * This is done by having a look at the "wchan" property of the
1512 * process, which tells where it is stopped (if it is). */
1513 FILE * status;
1514 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001515
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001516 sprintf(proc, "/proc/%d/status", tcp->pid);
1517 status = fopen(proc, "r");
1518 if (status &&
1519 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1520 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1521 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1522 strcmp(wchan, "stopevent")) {
1523 /* The process is asleep in the middle of a syscall.
1524 Fake the syscall entry event */
1525 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1526 tcp->status.PR_WHY = PR_SYSENTRY;
1527 trace_syscall(tcp);
1528 }
1529 if (status)
1530 fclose(status);
1531 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001532 }
1533#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534#ifndef HAVE_POLLABLE_PROCFS
1535 if (proc_poll_pipe[0] != -1)
1536 proc_poller(tcp->pfd);
1537 else if (nprocs > 1) {
1538 proc_poll_open();
1539 proc_poller(last_pfd);
1540 proc_poller(tcp->pfd);
1541 }
1542 last_pfd = tcp->pfd;
1543#endif /* !HAVE_POLLABLE_PROCFS */
1544 return 0;
1545}
1546
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001547#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001548
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001549struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001550pid2tcb(int pid)
1551{
1552 int i;
1553
1554 if (pid <= 0)
1555 return NULL;
1556
1557 for (i = 0; i < tcbtabsize; i++) {
1558 struct tcb *tcp = tcbtab[i];
1559 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1560 return tcp;
1561 }
1562
1563 return NULL;
1564}
1565
1566#ifdef USE_PROCFS
1567
1568static struct tcb *
1569first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570{
1571 int i;
1572 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001573 for (i = 0; i < tcbtabsize; i++) {
1574 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575 if (tcp->flags & TCB_INUSE)
1576 return tcp;
1577 }
1578 return NULL;
1579}
1580
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001582pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583{
1584 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585
Roland McGrathca16be82003-01-10 19:55:28 +00001586 for (i = 0; i < tcbtabsize; i++) {
1587 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588 if (tcp->pfd != pfd)
1589 continue;
1590 if (tcp->flags & TCB_INUSE)
1591 return tcp;
1592 }
1593 return NULL;
1594}
1595
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001596#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597
1598void
Denys Vlasenko12014262011-05-30 14:00:14 +02001599droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600{
1601 if (tcp->pid == 0)
1602 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001603
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001605 if (debug)
1606 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001607
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 if (tcp->pfd != -1) {
1609 close(tcp->pfd);
1610 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001611#ifdef FREEBSD
1612 if (tcp->pfd_reg != -1) {
1613 close(tcp->pfd_reg);
1614 tcp->pfd_reg = -1;
1615 }
1616 if (tcp->pfd_status != -1) {
1617 close(tcp->pfd_status);
1618 tcp->pfd_status = -1;
1619 }
Roland McGrath553a6092002-12-16 20:40:39 +00001620#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001621#ifdef USE_PROCFS
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001622 tcp->flags = 0; /* rebuild_pollv needs it */
1623 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624#endif
1625 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001626
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001627 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001629
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001630 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631}
1632
Roland McGrath0a463882007-07-05 18:43:16 +00001633/* detach traced process; continue with sig
1634 Never call DETACH twice on the same process as both unattached and
1635 attached-unstopped processes give the same ESRCH. For unattached process we
1636 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637
1638static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001639detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640{
1641 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001642#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001643 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001644#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645
1646 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001647 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648
1649#ifdef LINUX
1650 /*
1651 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001652 * before detaching. Arghh. We go through hoops
1653 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001655#if defined(SPARC)
1656#undef PTRACE_DETACH
1657#define PTRACE_DETACH PTRACE_SUNDETACH
1658#endif
Roland McGrath02203312007-06-11 22:06:31 +00001659 /*
1660 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1661 * expected SIGSTOP. We must catch exactly one as otherwise the
1662 * detached process would be left stopped (process state T).
1663 */
1664 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1666 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001667 }
1668 else if (errno != ESRCH) {
1669 /* Shouldn't happen. */
1670 perror("detach: ptrace(PTRACE_DETACH, ...)");
1671 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001672 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001673 if (errno != ESRCH)
1674 perror("detach: checking sanity");
1675 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001676 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001677 if (errno != ESRCH)
1678 perror("detach: stopping child");
1679 }
Roland McGrath02203312007-06-11 22:06:31 +00001680 else
1681 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001682 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001684#ifdef __WALL
1685 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1686 if (errno == ECHILD) /* Already gone. */
1687 break;
1688 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001689 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001690 break;
1691 }
1692#endif /* __WALL */
1693 /* No __WALL here. */
1694 if (waitpid(tcp->pid, &status, 0) < 0) {
1695 if (errno != ECHILD) {
1696 perror("detach: waiting");
1697 break;
1698 }
1699#ifdef __WCLONE
1700 /* If no processes, try clones. */
1701 if (wait4(tcp->pid, &status, __WCLONE,
1702 NULL) < 0) {
1703 if (errno != ECHILD)
1704 perror("detach: waiting");
1705 break;
1706 }
1707#endif /* __WCLONE */
1708 }
1709#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001710 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001711#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 if (!WIFSTOPPED(status)) {
1713 /* Au revoir, mon ami. */
1714 break;
1715 }
1716 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001717 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 break;
1719 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001720 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001721 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001722 : WSTOPSIG(status));
1723 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001726 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001727#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728
1729#if defined(SUNOS4)
1730 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1731 if (sig && kill(tcp->pid, sig) < 0)
1732 perror("detach: kill");
1733 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001734 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735#endif /* SUNOS4 */
1736
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737 if (!qflag)
1738 fprintf(stderr, "Process %u detached\n", tcp->pid);
1739
1740 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001741
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742 return error;
1743}
1744
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001745#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001747static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748{
1749 int pid;
1750 int status;
1751
1752 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 }
1754}
1755
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001756#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757
1758static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001759cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760{
1761 int i;
1762 struct tcb *tcp;
1763
Roland McGrathee9d4352002-12-18 04:16:10 +00001764 for (i = 0; i < tcbtabsize; i++) {
1765 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766 if (!(tcp->flags & TCB_INUSE))
1767 continue;
1768 if (debug)
1769 fprintf(stderr,
1770 "cleanup: looking at pid %u\n", tcp->pid);
1771 if (tcp_last &&
1772 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001773 tprintf(" <unfinished ...>");
1774 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775 }
1776 if (tcp->flags & TCB_ATTACHED)
1777 detach(tcp, 0);
1778 else {
1779 kill(tcp->pid, SIGCONT);
1780 kill(tcp->pid, SIGTERM);
1781 }
1782 }
1783 if (cflag)
1784 call_summary(outf);
1785}
1786
1787static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001788interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789{
1790 interrupted = 1;
1791}
1792
1793#ifndef HAVE_STRERROR
1794
Roland McGrath6d2b3492002-12-30 00:51:30 +00001795#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796extern int sys_nerr;
1797extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001798#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799
1800const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001801strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802{
1803 static char buf[64];
1804
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001805 if (err_no < 1 || err_no >= sys_nerr) {
1806 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807 return buf;
1808 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001809 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810}
1811
1812#endif /* HAVE_STERRROR */
1813
1814#ifndef HAVE_STRSIGNAL
1815
Roland McGrath8f474e02003-01-14 07:53:33 +00001816#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001817extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001819#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1820extern char *_sys_siglist[];
1821#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822
1823const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001824strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825{
1826 static char buf[64];
1827
1828 if (sig < 1 || sig >= NSIG) {
1829 sprintf(buf, "Unknown signal %d", sig);
1830 return buf;
1831 }
1832#ifdef HAVE__SYS_SIGLIST
1833 return _sys_siglist[sig];
1834#else
1835 return sys_siglist[sig];
1836#endif
1837}
1838
1839#endif /* HAVE_STRSIGNAL */
1840
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001841#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001842
1843static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001844rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845{
1846 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847
Roland McGrathee9d4352002-12-18 04:16:10 +00001848 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001849 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001850 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001851 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001852 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001853 }
1854
Roland McGrathca16be82003-01-10 19:55:28 +00001855 for (i = j = 0; i < tcbtabsize; i++) {
1856 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 if (!(tcp->flags & TCB_INUSE))
1858 continue;
1859 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001860 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861 j++;
1862 }
1863 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001864 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 }
1866}
1867
1868#ifndef HAVE_POLLABLE_PROCFS
1869
1870static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001871proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873 int i;
1874
1875 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001876 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877 }
1878 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001879 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 }
1881}
1882
1883static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001884proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885{
1886 int i;
1887 int n;
1888 struct proc_pollfd pollinfo;
1889
1890 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1891 return n;
1892 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001893 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001894 }
1895 for (i = 0; i < nprocs; i++) {
1896 if (pollv[i].fd == pollinfo.fd)
1897 pollv[i].revents = pollinfo.revents;
1898 else
1899 pollv[i].revents = 0;
1900 }
1901 poller_pid = pollinfo.pid;
1902 return 1;
1903}
1904
1905static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001906wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907{
1908}
1909
1910static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001911proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912{
1913 struct proc_pollfd pollinfo;
1914 struct sigaction sa;
1915 sigset_t blocked_set, empty_set;
1916 int i;
1917 int n;
1918 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001919#ifdef FREEBSD
1920 struct procfs_status pfs;
1921#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922
1923 switch (fork()) {
1924 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001925 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926 case 0:
1927 break;
1928 default:
1929 return;
1930 }
1931
1932 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1933 sa.sa_flags = 0;
1934 sigemptyset(&sa.sa_mask);
1935 sigaction(SIGHUP, &sa, NULL);
1936 sigaction(SIGINT, &sa, NULL);
1937 sigaction(SIGQUIT, &sa, NULL);
1938 sigaction(SIGPIPE, &sa, NULL);
1939 sigaction(SIGTERM, &sa, NULL);
1940 sa.sa_handler = wakeup_handler;
1941 sigaction(SIGUSR1, &sa, NULL);
1942 sigemptyset(&blocked_set);
1943 sigaddset(&blocked_set, SIGUSR1);
1944 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1945 sigemptyset(&empty_set);
1946
1947 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001948 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949 }
1950 n = rl.rlim_cur;
1951 for (i = 0; i < n; i++) {
1952 if (i != pfd && i != proc_poll_pipe[1])
1953 close(i);
1954 }
1955
1956 pollinfo.fd = pfd;
1957 pollinfo.pid = getpid();
1958 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001959#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001960 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1961#else
1962 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1963#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001964 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965 switch (errno) {
1966 case EINTR:
1967 continue;
1968 case EBADF:
1969 pollinfo.revents = POLLERR;
1970 break;
1971 case ENOENT:
1972 pollinfo.revents = POLLHUP;
1973 break;
1974 default:
1975 perror("proc_poller: PIOCWSTOP");
1976 }
1977 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1978 _exit(0);
1979 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001980 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1982 sigsuspend(&empty_set);
1983 }
1984}
1985
1986#endif /* !HAVE_POLLABLE_PROCFS */
1987
1988static int
1989choose_pfd()
1990{
1991 int i, j;
1992 struct tcb *tcp;
1993
1994 static int last;
1995
1996 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001997 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 /*
1999 * The previous process is ready to run again. We'll
2000 * let it do so if it is currently in a syscall. This
2001 * heuristic improves the readability of the trace.
2002 */
2003 tcp = pfd2tcb(pollv[last].fd);
2004 if (tcp && (tcp->flags & TCB_INSYSCALL))
2005 return pollv[last].fd;
2006 }
2007
2008 for (i = 0; i < nprocs; i++) {
2009 /* Let competing children run round robin. */
2010 j = (i + last + 1) % nprocs;
2011 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2012 tcp = pfd2tcb(pollv[j].fd);
2013 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002014 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 }
2016 droptcb(tcp);
2017 return -1;
2018 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002019 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002020 last = j;
2021 return pollv[j].fd;
2022 }
2023 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002024 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025}
2026
2027static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002028trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002030#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002031 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002032#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033 struct tcb *tcp;
2034 int pfd;
2035 int what;
2036 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002037 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038
2039 for (;;) {
2040 if (interactive)
2041 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2042
2043 if (nprocs == 0)
2044 break;
2045
2046 switch (nprocs) {
2047 case 1:
2048#ifndef HAVE_POLLABLE_PROCFS
2049 if (proc_poll_pipe[0] == -1) {
2050#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002051 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052 if (!tcp)
2053 continue;
2054 pfd = tcp->pfd;
2055 if (pfd == -1)
2056 continue;
2057 break;
2058#ifndef HAVE_POLLABLE_PROCFS
2059 }
2060 /* fall through ... */
2061#endif /* !HAVE_POLLABLE_PROCFS */
2062 default:
2063#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002064#ifdef POLL_HACK
2065 /* On some systems (e.g. UnixWare) we get too much ugly
2066 "unfinished..." stuff when multiple proceses are in
2067 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002068
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002069 if (in_syscall) {
2070 struct pollfd pv;
2071 tcp = in_syscall;
2072 in_syscall = NULL;
2073 pv.fd = tcp->pfd;
2074 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002075 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002076 if (interrupted)
2077 return 0;
2078 continue;
2079 }
2080 else if (what == 1 && pv.revents & POLLWANT) {
2081 goto FOUND;
2082 }
2083 }
2084#endif
2085
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002086 if (poll(pollv, nprocs, INFTIM) < 0) {
2087 if (interrupted)
2088 return 0;
2089 continue;
2090 }
2091#else /* !HAVE_POLLABLE_PROCFS */
2092 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2093 if (interrupted)
2094 return 0;
2095 continue;
2096 }
2097#endif /* !HAVE_POLLABLE_PROCFS */
2098 pfd = choose_pfd();
2099 if (pfd == -1)
2100 continue;
2101 break;
2102 }
2103
2104 /* Look up `pfd' in our table. */
2105 if ((tcp = pfd2tcb(pfd)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002106 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 }
John Hughesb6643082002-05-23 11:02:22 +00002108#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002109 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002110#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111 /* Get the status of the process. */
2112 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002113#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002114 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002115#else /* FREEBSD */
2116 /* Thanks to some scheduling mystery, the first poller
2117 sometimes waits for the already processed end of fork
2118 event. Doing a non blocking poll here solves the problem. */
2119 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002120 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002121 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002122 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002123#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002124 ioctl_errno = errno;
2125#ifndef HAVE_POLLABLE_PROCFS
2126 if (proc_poll_pipe[0] != -1) {
2127 if (ioctl_result < 0)
2128 kill(poller_pid, SIGKILL);
2129 else
2130 kill(poller_pid, SIGUSR1);
2131 }
2132#endif /* !HAVE_POLLABLE_PROCFS */
2133 }
2134 if (interrupted)
2135 return 0;
2136
2137 if (interactive)
2138 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2139
2140 if (ioctl_result < 0) {
2141 /* Find out what happened if it failed. */
2142 switch (ioctl_errno) {
2143 case EINTR:
2144 case EBADF:
2145 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002146#ifdef FREEBSD
2147 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002148#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 case ENOENT:
2150 droptcb(tcp);
2151 continue;
2152 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002153 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 }
2155 }
2156
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002157#ifdef FREEBSD
2158 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2159 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002160 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002161 continue;
2162 }
Roland McGrath553a6092002-12-16 20:40:39 +00002163#endif
2164
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002165 /* clear the just started flag */
2166 tcp->flags &= ~TCB_STARTUP;
2167
2168 /* set current output file */
2169 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002170 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171
2172 if (cflag) {
2173 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002174#ifdef FREEBSD
2175 char buf[1024];
2176 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002178 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2179 buf[len] = '\0';
2180 sscanf(buf,
2181 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2182 &stime.tv_sec, &stime.tv_usec);
2183 } else
2184 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002185#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2187 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002188#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2190 tcp->stime = stime;
2191 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002192 what = tcp->status.PR_WHAT;
2193 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002194#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002196 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2197 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002199 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 }
2201 }
2202 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002203#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002205#ifdef POLL_HACK
2206 in_syscall = tcp;
2207#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208 case PR_SYSEXIT:
2209 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002210 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 }
2212 break;
2213 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002214 if (cflag != CFLAG_ONLY_STATS
2215 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002216 printleader(tcp);
2217 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002218 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002219 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002220#ifdef PR_INFO
2221 if (tcp->status.PR_INFO.si_signo == what) {
2222 printleader(tcp);
2223 tprintf(" siginfo=");
2224 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002225 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002226 }
2227#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002228 }
2229 break;
2230 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002231 if (cflag != CFLAGS_ONLY_STATS
2232 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 printleader(tcp);
2234 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002235 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 }
2237 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002238#ifdef FREEBSD
2239 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002240 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002241#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002242 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002243 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244 break;
2245 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002246 /* Remember current print column before continuing. */
2247 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002248 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002249#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002250 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002251#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002252 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002253#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002254 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002255 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 }
2257 }
2258 return 0;
2259}
2260
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002261#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002262
Roland McGratheb9e2e82009-06-02 16:49:22 -07002263static int
2264trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265{
2266 int pid;
2267 int wait_errno;
2268 int status;
2269 struct tcb *tcp;
2270#ifdef LINUX
2271 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002272 struct rusage *rup = cflag ? &ru : NULL;
2273# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002274 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002275# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002276#endif /* LINUX */
2277
Roland McGratheb9e2e82009-06-02 16:49:22 -07002278 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002279 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002280 return 0;
2281 if (interactive)
2282 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002284# ifdef __WALL
2285 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002286 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002287 /* this kernel does not support __WALL */
2288 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002289 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002290 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002291 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002292 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002293 pid = wait4(-1, &status, __WCLONE, rup);
2294 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002295 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002296 }
2297 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002298# else
2299 pid = wait4(-1, &status, 0, rup);
2300# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002301#endif /* LINUX */
2302#ifdef SUNOS4
2303 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002304#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002306 if (interactive)
2307 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002309 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002310 switch (wait_errno) {
2311 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002313 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002314 /*
2315 * We would like to verify this case
2316 * but sometimes a race in Solbourne's
2317 * version of SunOS sometimes reports
2318 * ECHILD before sending us SIGCHILD.
2319 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002320 return 0;
2321 default:
2322 errno = wait_errno;
2323 perror("strace: wait");
2324 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002325 }
2326 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002327 if (pid == popen_pid) {
2328 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002329 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002330 continue;
2331 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002332 if (debug) {
2333 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2334#ifdef LINUX
2335 unsigned ev = (unsigned)status >> 16;
2336 if (ev) {
2337 static const char *const event_names[] = {
2338 [PTRACE_EVENT_CLONE] = "CLONE",
2339 [PTRACE_EVENT_FORK] = "FORK",
2340 [PTRACE_EVENT_VFORK] = "VFORK",
2341 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2342 [PTRACE_EVENT_EXEC] = "EXEC",
2343 [PTRACE_EVENT_EXIT] = "EXIT",
2344 };
2345 const char *e;
2346 if (ev < ARRAY_SIZE(event_names))
2347 e = event_names[ev];
2348 else {
2349 sprintf(buf, "?? (%u)", ev);
2350 e = buf;
2351 }
2352 fprintf(stderr, " PTRACE_EVENT_%s", e);
2353 }
2354#endif
2355 strcpy(buf, "???");
2356 if (WIFSIGNALED(status))
2357#ifdef WCOREDUMP
2358 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2359 WCOREDUMP(status) ? "core," : "",
2360 signame(WTERMSIG(status)));
2361#else
2362 sprintf(buf, "WIFSIGNALED,sig=%s",
2363 signame(WTERMSIG(status)));
2364#endif
2365 if (WIFEXITED(status))
2366 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2367 if (WIFSTOPPED(status))
2368 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002369#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002370 if (WIFCONTINUED(status))
2371 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002372#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002373 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2374 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002375
2376 /* Look up `pid' in our table. */
2377 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002378#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002379 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002380 /* This is needed to go with the CLONE_PTRACE
2381 changes in process.c/util.c: we might see
2382 the child's initial trap before we see the
2383 parent return from the clone syscall.
2384 Leave the child suspended until the parent
2385 returns from its system call. Only then
2386 will we have the association of parent and
2387 child so that we know how to do clearbpt
2388 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002389 tcp = alloctcb(pid);
Denys Vlasenko833fb132011-08-17 11:30:56 +02002390 tcp->flags |= TCB_ATTACHED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002391 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002392 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002393 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002394 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002395 else
2396 /* This can happen if a clone call used
2397 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002398#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002399 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002400 if (WIFSTOPPED(status))
2401 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002402 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002403 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002404 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002405 /* set current output file */
2406 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002407 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002408#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002409 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002410 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2411 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002412 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002413#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002414
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002416 if (pid == strace_child)
2417 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002418 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002419 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2420 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002421#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002422 tprintf("+++ killed by %s %s+++",
2423 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002424 WCOREDUMP(status) ? "(core dumped) " : "");
2425#else
2426 tprintf("+++ killed by %s +++",
2427 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002428#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002429 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002430 }
2431 droptcb(tcp);
2432 continue;
2433 }
2434 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002435 if (pid == strace_child)
2436 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002437 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002438 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002439 tprintf(" <unfinished ... exit status %d>\n",
2440 WEXITSTATUS(status));
2441 tcp_last = NULL;
2442 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002443 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2444 printleader(tcp);
2445 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2446 printtrailer();
2447 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002448 droptcb(tcp);
2449 continue;
2450 }
2451 if (!WIFSTOPPED(status)) {
2452 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2453 droptcb(tcp);
2454 continue;
2455 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002457 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002458 /* Ptrace event (we ignore all of them for now) */
2459 goto tracing;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002460 }
2461
Roland McGrath02203312007-06-11 22:06:31 +00002462 /*
2463 * Interestingly, the process may stop
2464 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002465 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002466 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002467 * A no-MMU vforked child won't send up a signal,
2468 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002469 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002470 if ((tcp->flags & TCB_STARTUP) &&
2471 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 /*
2473 * This flag is there to keep us in sync.
2474 * Next time this process stops it should
2475 * really be entering a system call.
2476 */
2477 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002479 /*
2480 * One example is a breakpoint inherited from
2481 * parent through fork ().
2482 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002483 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2484 droptcb(tcp);
2485 cleanup();
2486 return -1;
2487 }
2488 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002489#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002490 if (ptrace_setoptions) {
2491 if (debug)
2492 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2493 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2494 if (errno != ESRCH) {
2495 /* Should never happen, really */
2496 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002497 }
2498 }
2499 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002500#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002501 goto tracing;
2502 }
2503
Denys Vlasenko75422762011-05-27 14:36:01 +02002504 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002505 if (WSTOPSIG(status) == SIGSTOP &&
2506 (tcp->flags & TCB_SIGTRAPPED)) {
2507 /*
2508 * Trapped attempt to block SIGTRAP
2509 * Hope we are back in control now.
2510 */
2511 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002512 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513 cleanup();
2514 return -1;
2515 }
2516 continue;
2517 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002518 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002519 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002520 siginfo_t si;
2521#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002522 long pc = 0;
2523 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002524
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002525 upeek(tcp, PT_CR_IPSR, &psr);
2526 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002527
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002528# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002529 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002530# define PC_FORMAT_STR " @ %lx"
2531# define PC_FORMAT_ARG pc
2532#else
2533# define PC_FORMAT_STR "%s"
2534# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002535#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002536 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002537 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2538 tprintf("--- ");
2539 printsiginfo(&si, verbose(tcp));
2540 tprintf(" (%s)" PC_FORMAT_STR " ---",
2541 strsignal(WSTOPSIG(status)),
2542 PC_FORMAT_ARG);
2543 } else
2544 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2545 strsignal(WSTOPSIG(status)),
2546 signame(WSTOPSIG(status)),
2547 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002548 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002549 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002550 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 cleanup();
2552 return -1;
2553 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002554 continue;
2555 }
Roland McGrath02203312007-06-11 22:06:31 +00002556 /* we handled the STATUS, we are permitted to interrupt now. */
2557 if (interrupted)
2558 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002559 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2560 /* ptrace() failed in trace_syscall() with ESRCH.
2561 * Likely a result of process disappearing mid-flight.
2562 * Observed case: exit_group() terminating
2563 * all processes in thread group. In this case, threads
2564 * "disappear" in an unpredictable moment without any
2565 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002566 */
2567 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002568 if (tcp_last) {
2569 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002570 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002571 */
2572 tcp_last->flags |= TCB_REPRINT;
2573 tprintf(" <unfinished ...>");
2574 printtrailer();
2575 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002576 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002577 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002578 ptrace(PTRACE_KILL,
2579 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002580 droptcb(tcp);
2581 }
2582 continue;
2583 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002585 /* Remember current print column before continuing. */
2586 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002587 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002588 cleanup();
2589 return -1;
2590 }
2591 }
2592 return 0;
2593}
2594
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002595#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002596
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002597void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002598tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002599{
2600 va_list args;
2601
Andreas Schwabe5355de2009-10-27 16:56:43 +01002602 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002603 if (outf) {
2604 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002605 if (n < 0) {
2606 if (outf != stderr)
2607 perror(outfname == NULL
2608 ? "<writing to pipe>" : outfname);
2609 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002610 curcol += n;
2611 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002612 va_end(args);
2613 return;
2614}
2615
2616void
Denys Vlasenko12014262011-05-30 14:00:14 +02002617printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002618{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002619 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002620 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002621 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002622 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002623 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002624 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002625 tprintf("= ? <unavailable>\n");
2626 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002627 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002628 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002629 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002630 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002631 }
2632 curcol = 0;
2633 if ((followfork == 1 || pflag_seen > 1) && outfname)
2634 tprintf("%-5d ", tcp->pid);
2635 else if (nprocs > 1 && !outfname)
2636 tprintf("[pid %5u] ", tcp->pid);
2637 if (tflag) {
2638 char str[sizeof("HH:MM:SS")];
2639 struct timeval tv, dtv;
2640 static struct timeval otv;
2641
2642 gettimeofday(&tv, NULL);
2643 if (rflag) {
2644 if (otv.tv_sec == 0)
2645 otv = tv;
2646 tv_sub(&dtv, &tv, &otv);
2647 tprintf("%6ld.%06ld ",
2648 (long) dtv.tv_sec, (long) dtv.tv_usec);
2649 otv = tv;
2650 }
2651 else if (tflag > 2) {
2652 tprintf("%ld.%06ld ",
2653 (long) tv.tv_sec, (long) tv.tv_usec);
2654 }
2655 else {
2656 time_t local = tv.tv_sec;
2657 strftime(str, sizeof(str), "%T", localtime(&local));
2658 if (tflag > 1)
2659 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2660 else
2661 tprintf("%s ", str);
2662 }
2663 }
2664 if (iflag)
2665 printcall(tcp);
2666}
2667
2668void
Denys Vlasenko12014262011-05-30 14:00:14 +02002669tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670{
2671 if (curcol < col)
2672 tprintf("%*s", col - curcol, "");
2673}
2674
2675void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002676printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002677{
2678 tprintf("\n");
2679 tcp_last = NULL;
2680}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002681
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002682#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002683
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002684int
2685mp_ioctl(int fd, int cmd, void *arg, int size)
2686{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002687 struct iovec iov[2];
2688 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002689
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002690 iov[0].iov_base = &cmd;
2691 iov[0].iov_len = sizeof cmd;
2692 if (arg) {
2693 ++n;
2694 iov[1].iov_base = arg;
2695 iov[1].iov_len = size;
2696 }
Roland McGrath553a6092002-12-16 20:40:39 +00002697
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002698 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002699}
2700
2701#endif