blob: 1d79cc448177a6ce13f1f2ce5477fba51b16bd63 [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
726/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000727 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800728 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000729 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800730 */
731static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200732test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800733{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000734 int pid, expected_grandchild = 0, found_grandchild = 0;
735 const unsigned int test_options = PTRACE_O_TRACECLONE |
736 PTRACE_O_TRACEFORK |
737 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800738
739 if ((pid = fork()) < 0)
740 return -1;
741 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000742 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800743 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800744 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000745 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800746 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000747
748 while (1) {
749 int status, tracee_pid;
750
751 tracee_pid = wait(&status);
752 if (tracee_pid == -1) {
753 if (errno == EINTR)
754 continue;
755 else if (errno == ECHILD)
756 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200757 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000758 return -1;
759 }
760 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000761 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000762 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
763 errno != ESRCH)
764 kill(tracee_pid, SIGKILL);
765 }
766 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000767 switch (WSTOPSIG(status)) {
768 case SIGSTOP:
769 if (ptrace(PTRACE_SETOPTIONS, pid,
770 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000771 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800772 return -1;
773 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000774 break;
775 case SIGTRAP:
776 if (status >> 16 == PTRACE_EVENT_FORK) {
777 long msg = 0;
778
779 if (ptrace(PTRACE_GETEVENTMSG, pid,
780 NULL, (long) &msg) == 0)
781 expected_grandchild = msg;
782 }
783 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800784 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000785 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
786 errno != ESRCH)
787 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800788 }
789 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000790 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200791 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800792 return 0;
793}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200794
795/*
796 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
797 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
798 * and then see whether it will stop with (SIGTRAP | 0x80).
799 *
800 * Use of this option enables correct handling of user-generated SIGTRAPs,
801 * and SIGTRAPs generated by special instructions such as int3 on x86:
802 * _start: .globl _start
803 * int3
804 * movl $42, %ebx
805 * movl $1, %eax
806 * int $0x80
807 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
808 */
809static void
810test_ptrace_setoptions_for_all(void)
811{
812 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
813 int pid;
814 int it_worked = 0;
815
816 pid = fork();
817 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200818 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200819
820 if (pid == 0) {
821 pid = getpid();
822 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200823 /* Note: exits with exitcode 1 */
824 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200825 kill(pid, SIGSTOP);
826 _exit(0); /* parent should see entry into this syscall */
827 }
828
829 while (1) {
830 int status, tracee_pid;
831
832 errno = 0;
833 tracee_pid = wait(&status);
834 if (tracee_pid <= 0) {
835 if (errno == EINTR)
836 continue;
837 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200838 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200839 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200840 if (WIFEXITED(status)) {
841 if (WEXITSTATUS(status) == 0)
842 break;
843 /* PTRACE_TRACEME failed in child. This is fatal. */
844 exit(1);
845 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200846 if (!WIFSTOPPED(status)) {
847 kill(pid, SIGKILL);
848 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
849 }
850 if (WSTOPSIG(status) == SIGSTOP) {
851 /*
852 * We don't check "options aren't accepted" error.
853 * If it happens, we'll never get (SIGTRAP | 0x80),
854 * and thus will decide to not use the option.
855 * IOW: the outcome of the test will be correct.
856 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200857 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
858 if (errno != EINVAL)
859 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200860 }
861 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
862 it_worked = 1;
863 }
864 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
865 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200866 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200867 }
868 }
869
870 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200871 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200872 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200873 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200874 fprintf(stderr, "ptrace_setoptions = %#x\n",
875 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200876 return;
877 }
878
879 fprintf(stderr,
880 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
881}
Wang Chaob13c0de2010-11-12 17:25:19 +0800882#endif
883
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000885main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000887 struct tcb *tcp;
888 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000889 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000890 struct sigaction sa;
891
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000892 progname = argv[0] ? argv[0] : "strace";
893
Denys Vlasenko75422762011-05-27 14:36:01 +0200894 strace_tracer_pid = getpid();
895
Roland McGrathee9d4352002-12-18 04:16:10 +0000896 /* Allocate the initial tcbtab. */
897 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200898 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200899 if (tcbtab == NULL)
900 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200901 tcp = calloc(tcbtabsize, sizeof(*tcp));
902 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200903 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200904 for (c = 0; c < tcbtabsize; c++)
905 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000906
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000907 outf = stderr;
908 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000909 set_sortby(DEFAULT_SORTBY);
910 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000911 qualify("trace=all");
912 qualify("abbrev=all");
913 qualify("verbose=all");
914 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000916 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000917#ifndef USE_PROCFS
918 "D"
919#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000920 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000921 switch (c) {
922 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000923 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200924 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000925 }
926 cflag = CFLAG_ONLY_STATS;
927 break;
928 case 'C':
929 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200930 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000931 }
932 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933 break;
934 case 'd':
935 debug++;
936 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000937#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000938 case 'D':
939 daemonized_tracer = 1;
940 break;
941#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000942 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000943 optF = 1;
944 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 case 'f':
946 followfork++;
947 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 case 'h':
949 usage(stdout, 0);
950 break;
951 case 'i':
952 iflag++;
953 break;
954 case 'q':
955 qflag++;
956 break;
957 case 'r':
958 rflag++;
959 tflag++;
960 break;
961 case 't':
962 tflag++;
963 break;
964 case 'T':
965 dtime++;
966 break;
967 case 'x':
968 xflag++;
969 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000970 case 'y':
971 show_fd_path = 1;
972 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 case 'v':
974 qualify("abbrev=none");
975 break;
976 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000977 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 exit(0);
979 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000980 case 'z':
981 not_failing_only = 1;
982 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 case 'a':
984 acolumn = atoi(optarg);
985 break;
986 case 'e':
987 qualify(optarg);
988 break;
989 case 'o':
990 outfname = strdup(optarg);
991 break;
992 case 'O':
993 set_overhead(atoi(optarg));
994 break;
995 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000996 if ((pid = atoi(optarg)) <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200997 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 break;
999 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001000 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001001 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 break;
1003 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001004 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 tcp->flags |= TCB_ATTACHED;
1006 pflag_seen++;
1007 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001008 case 'P':
1009 tracing_paths = 1;
1010 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001011 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001012 }
1013 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 case 's':
1015 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001016 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001017 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001018 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 break;
1020 case 'S':
1021 set_sortby(optarg);
1022 break;
1023 case 'u':
1024 username = strdup(optarg);
1025 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001026 case 'E':
1027 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001028 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001029 }
1030 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 default:
1032 usage(stderr, 1);
1033 break;
1034 }
1035 }
1036
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001037 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001038 usage(stderr, 1);
1039
Wang Chaod322a4b2010-08-05 14:30:11 +08001040 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001041 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001042 }
1043
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001044 if (!followfork)
1045 followfork = optF;
1046
Roland McGrathcb9def62006-04-25 07:48:03 +00001047 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001048 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001049 }
1050
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 /* See if they want to run as another user. */
1052 if (username != NULL) {
1053 struct passwd *pent;
1054
1055 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001056 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 }
1058 if ((pent = getpwnam(username)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001059 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 }
1061 run_uid = pent->pw_uid;
1062 run_gid = pent->pw_gid;
1063 }
1064 else {
1065 run_uid = getuid();
1066 run_gid = getgid();
1067 }
1068
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001069#ifdef LINUX
1070 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001071 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001072 fprintf(stderr,
1073 "Test for options supported by PTRACE_SETOPTIONS "
1074 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001075 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001076 }
1077 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001078 fprintf(stderr, "ptrace_setoptions = %#x\n",
1079 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001080 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001081 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001082#endif
1083
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 /* Check if they want to redirect the output. */
1085 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001086 /* See if they want to pipe the output. */
1087 if (outfname[0] == '|' || outfname[0] == '!') {
1088 /*
1089 * We can't do the <outfname>.PID funny business
1090 * when using popen, so prohibit it.
1091 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001092 if (followfork > 1)
1093 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1094 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001095 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001096 else if (followfork <= 1)
1097 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098 }
1099
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001100 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1101 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001102 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001103 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001104 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001107 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001108
Roland McGrath54cc1c82007-11-03 23:34:11 +00001109 /* Valid states here:
1110 optind < argc pflag_seen outfname interactive
1111 1 0 0 1
1112 0 1 0 1
1113 1 0 1 0
1114 0 1 1 1
1115 */
1116
1117 /* STARTUP_CHILD must be called before the signal handlers get
1118 installed below as they are inherited into the spawned process.
1119 Also we do not need to be protected by them as during interruption
1120 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1121 if (!pflag_seen)
1122 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 sigemptyset(&empty_set);
1125 sigemptyset(&blocked_set);
1126 sa.sa_handler = SIG_IGN;
1127 sigemptyset(&sa.sa_mask);
1128 sa.sa_flags = 0;
1129 sigaction(SIGTTOU, &sa, NULL);
1130 sigaction(SIGTTIN, &sa, NULL);
1131 if (interactive) {
1132 sigaddset(&blocked_set, SIGHUP);
1133 sigaddset(&blocked_set, SIGINT);
1134 sigaddset(&blocked_set, SIGQUIT);
1135 sigaddset(&blocked_set, SIGPIPE);
1136 sigaddset(&blocked_set, SIGTERM);
1137 sa.sa_handler = interrupt;
1138#ifdef SUNOS4
1139 /* POSIX signals on sunos4.1 are a little broken. */
1140 sa.sa_flags = SA_INTERRUPT;
1141#endif /* SUNOS4 */
1142 }
1143 sigaction(SIGHUP, &sa, NULL);
1144 sigaction(SIGINT, &sa, NULL);
1145 sigaction(SIGQUIT, &sa, NULL);
1146 sigaction(SIGPIPE, &sa, NULL);
1147 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001148#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 sa.sa_handler = reaper;
1150 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001151#else
1152 /* Make sure SIGCHLD has the default action so that waitpid
1153 definitely works without losing track of children. The user
1154 should not have given us a bogus state to inherit, but he might
1155 have. Arguably we should detect SIG_IGN here and pass it on
1156 to children, but probably noone really needs that. */
1157 sa.sa_handler = SIG_DFL;
1158 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001159#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001161 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001162 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001163
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164 if (trace() < 0)
1165 exit(1);
1166 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001167 fflush(NULL);
1168 if (exit_code > 0xff) {
1169 /* Child was killed by a signal, mimic that. */
1170 exit_code &= 0xff;
1171 signal(exit_code, SIG_DFL);
1172 raise(exit_code);
1173 /* Paranoia - what if this signal is not fatal?
1174 Exit with 128 + signo then. */
1175 exit_code += 128;
1176 }
1177 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178}
1179
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001180static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001181expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001182{
1183 /* Allocate some more TCBs and expand the table.
1184 We don't want to relocate the TCBs because our
1185 callers have pointers and it would be a pain.
1186 So tcbtab is a table of pointers. Since we never
1187 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001188 int i = tcbtabsize;
1189 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1190 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1191 if (newtab == NULL || newtcbs == NULL)
1192 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001193 tcbtabsize *= 2;
1194 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001195 while (i < tcbtabsize)
1196 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001197}
1198
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001200alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201{
1202 int i;
1203 struct tcb *tcp;
1204
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001205 if (nprocs == tcbtabsize)
1206 expand_tcbtab();
1207
Roland McGrathee9d4352002-12-18 04:16:10 +00001208 for (i = 0; i < tcbtabsize; i++) {
1209 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001211 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 tcp->flags = TCB_INUSE | TCB_STARTUP;
1214 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 tcp->pfd = -1;
1216 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001217 if (debug)
1218 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001219 if (command_options_parsed)
1220 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221 return tcp;
1222 }
1223 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001224 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225}
1226
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001227#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001229proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230{
1231 char proc[32];
1232 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001233#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001234 int i;
1235 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 sigset_t signals;
1237 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001238#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239#ifndef HAVE_POLLABLE_PROCFS
1240 static int last_pfd;
1241#endif
1242
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001243#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001244 /* Open the process pseudo-files in /proc. */
1245 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1246 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247 perror("strace: open(\"/proc/...\", ...)");
1248 return -1;
1249 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001250 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001251 sprintf(proc, "/proc/%d/status", tcp->pid);
1252 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1253 perror("strace: open(\"/proc/...\", ...)");
1254 return -1;
1255 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001256 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001257 sprintf(proc, "/proc/%d/as", tcp->pid);
1258 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1259 perror("strace: open(\"/proc/...\", ...)");
1260 return -1;
1261 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001262 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001263#else
1264 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001265#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001266 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001267 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001268#else /* FREEBSD */
1269 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001270 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001271#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001272 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001273 perror("strace: open(\"/proc/...\", ...)");
1274 return -1;
1275 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001276 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001277#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001278#ifdef FREEBSD
1279 sprintf(proc, "/proc/%d/regs", tcp->pid);
1280 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1281 perror("strace: open(\"/proc/.../regs\", ...)");
1282 return -1;
1283 }
1284 if (cflag) {
1285 sprintf(proc, "/proc/%d/status", tcp->pid);
1286 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1287 perror("strace: open(\"/proc/.../status\", ...)");
1288 return -1;
1289 }
1290 } else
1291 tcp->pfd_status = -1;
1292#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001293 rebuild_pollv();
1294 if (!attaching) {
1295 /*
1296 * Wait for the child to pause. Because of a race
1297 * condition we have to poll for the event.
1298 */
1299 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001300 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001301 perror("strace: PIOCSTATUS");
1302 return -1;
1303 }
1304 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001305 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001306 }
1307 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001308#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001309 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001310 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001311 perror("strace: PIOCSTOP");
1312 return -1;
1313 }
Roland McGrath553a6092002-12-16 20:40:39 +00001314#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315#ifdef PIOCSET
1316 /* Set Run-on-Last-Close. */
1317 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001318 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 perror("PIOCSET PR_RLC");
1320 return -1;
1321 }
1322 /* Set or Reset Inherit-on-Fork. */
1323 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001324 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325 perror("PIOC{SET,RESET} PR_FORK");
1326 return -1;
1327 }
1328#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001329#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1331 perror("PIOCSRLC");
1332 return -1;
1333 }
1334 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1335 perror("PIOC{S,R}FORK");
1336 return -1;
1337 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338#else /* FREEBSD */
1339 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1340 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1341 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001342 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001343 }
1344 arg &= ~PF_LINGER;
1345 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001346 perror("PIOCSFL");
1347 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001348 }
1349#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001351#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001352 /* Enable all syscall entries we care about. */
1353 premptyset(&syscalls);
1354 for (i = 1; i < MAX_QUALS; ++i) {
1355 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001356 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001357 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001358 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001359 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001360 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001361#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001362 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001363#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001364#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001365 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001366#endif
1367#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001368 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001369#endif
1370#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001371 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001372#endif
1373 }
1374 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375 perror("PIOCSENTRY");
1376 return -1;
1377 }
John Hughes19e49982001-10-19 08:59:12 +00001378 /* Enable the syscall exits. */
1379 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380 perror("PIOSEXIT");
1381 return -1;
1382 }
John Hughes19e49982001-10-19 08:59:12 +00001383 /* Enable signals we care about. */
1384 premptyset(&signals);
1385 for (i = 1; i < MAX_QUALS; ++i) {
1386 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001387 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001388 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001389 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390 perror("PIOCSTRACE");
1391 return -1;
1392 }
John Hughes19e49982001-10-19 08:59:12 +00001393 /* Enable faults we care about */
1394 premptyset(&faults);
1395 for (i = 1; i < MAX_QUALS; ++i) {
1396 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001397 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001398 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001399 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001400 perror("PIOCSFAULT");
1401 return -1;
1402 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001403#else /* FREEBSD */
1404 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001405 arg = S_SIG | S_SCE | S_SCX;
1406 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001407 perror("PIOCBIS");
1408 return -1;
1409 }
1410#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411 if (!attaching) {
1412#ifdef MIPS
1413 /*
1414 * The SGI PRSABORT doesn't work for pause() so
1415 * we send it a caught signal to wake it up.
1416 */
1417 kill(tcp->pid, SIGINT);
1418#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001419#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001420 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001421 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001422 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423 perror("PIOCRUN");
1424 return -1;
1425 }
Roland McGrath553a6092002-12-16 20:40:39 +00001426#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001427#endif /* !MIPS*/
1428#ifdef FREEBSD
1429 /* wake up the child if it received the SIGSTOP */
1430 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001431#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432 for (;;) {
1433 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001434 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 perror("PIOCWSTOP");
1436 return -1;
1437 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001438 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001439 tcp->flags &= ~TCB_INSYSCALL;
1440 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001441 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 break;
1443 }
1444 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001445#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001446 arg = 0;
1447 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001448#else /* FREEBSD */
1449 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001450#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 perror("PIOCRUN");
1452 return -1;
1453 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001454#ifdef FREEBSD
1455 /* handle the case where we "opened" the child before
1456 it did the kill -STOP */
1457 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1458 tcp->status.PR_WHAT == SIGSTOP)
1459 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001460#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001462#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001463 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001464#else /* FREEBSD */
1465 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001466 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001467 /* We are attaching to an already running process.
1468 * Try to figure out the state of the process in syscalls,
1469 * to handle the first event well.
1470 * This is done by having a look at the "wchan" property of the
1471 * process, which tells where it is stopped (if it is). */
1472 FILE * status;
1473 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001474
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001475 sprintf(proc, "/proc/%d/status", tcp->pid);
1476 status = fopen(proc, "r");
1477 if (status &&
1478 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1479 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1480 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1481 strcmp(wchan, "stopevent")) {
1482 /* The process is asleep in the middle of a syscall.
1483 Fake the syscall entry event */
1484 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1485 tcp->status.PR_WHY = PR_SYSENTRY;
1486 trace_syscall(tcp);
1487 }
1488 if (status)
1489 fclose(status);
1490 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001491 }
1492#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493#ifndef HAVE_POLLABLE_PROCFS
1494 if (proc_poll_pipe[0] != -1)
1495 proc_poller(tcp->pfd);
1496 else if (nprocs > 1) {
1497 proc_poll_open();
1498 proc_poller(last_pfd);
1499 proc_poller(tcp->pfd);
1500 }
1501 last_pfd = tcp->pfd;
1502#endif /* !HAVE_POLLABLE_PROCFS */
1503 return 0;
1504}
1505
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001506#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001508struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001509pid2tcb(int pid)
1510{
1511 int i;
1512
1513 if (pid <= 0)
1514 return NULL;
1515
1516 for (i = 0; i < tcbtabsize; i++) {
1517 struct tcb *tcp = tcbtab[i];
1518 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1519 return tcp;
1520 }
1521
1522 return NULL;
1523}
1524
1525#ifdef USE_PROCFS
1526
1527static struct tcb *
1528first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529{
1530 int i;
1531 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001532 for (i = 0; i < tcbtabsize; i++) {
1533 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 if (tcp->flags & TCB_INUSE)
1535 return tcp;
1536 }
1537 return NULL;
1538}
1539
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001541pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542{
1543 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544
Roland McGrathca16be82003-01-10 19:55:28 +00001545 for (i = 0; i < tcbtabsize; i++) {
1546 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 if (tcp->pfd != pfd)
1548 continue;
1549 if (tcp->flags & TCB_INUSE)
1550 return tcp;
1551 }
1552 return NULL;
1553}
1554
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001555#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556
1557void
Denys Vlasenko12014262011-05-30 14:00:14 +02001558droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559{
1560 if (tcp->pid == 0)
1561 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001562
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001564 if (debug)
1565 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001566
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 if (tcp->pfd != -1) {
1568 close(tcp->pfd);
1569 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001570#ifdef FREEBSD
1571 if (tcp->pfd_reg != -1) {
1572 close(tcp->pfd_reg);
1573 tcp->pfd_reg = -1;
1574 }
1575 if (tcp->pfd_status != -1) {
1576 close(tcp->pfd_status);
1577 tcp->pfd_status = -1;
1578 }
Roland McGrath553a6092002-12-16 20:40:39 +00001579#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001580#ifdef USE_PROCFS
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001581 tcp->flags = 0; /* rebuild_pollv needs it */
1582 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583#endif
1584 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001585
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001586 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001588
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001589 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590}
1591
Roland McGrath0a463882007-07-05 18:43:16 +00001592/* detach traced process; continue with sig
1593 Never call DETACH twice on the same process as both unattached and
1594 attached-unstopped processes give the same ESRCH. For unattached process we
1595 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596
1597static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001598detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599{
1600 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001601#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001602 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001603#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604
1605 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001606 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607
1608#ifdef LINUX
1609 /*
1610 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001611 * before detaching. Arghh. We go through hoops
1612 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001614#if defined(SPARC)
1615#undef PTRACE_DETACH
1616#define PTRACE_DETACH PTRACE_SUNDETACH
1617#endif
Roland McGrath02203312007-06-11 22:06:31 +00001618 /*
1619 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1620 * expected SIGSTOP. We must catch exactly one as otherwise the
1621 * detached process would be left stopped (process state T).
1622 */
1623 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1625 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001626 }
1627 else if (errno != ESRCH) {
1628 /* Shouldn't happen. */
1629 perror("detach: ptrace(PTRACE_DETACH, ...)");
1630 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001631 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001632 if (errno != ESRCH)
1633 perror("detach: checking sanity");
1634 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001635 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001636 if (errno != ESRCH)
1637 perror("detach: stopping child");
1638 }
Roland McGrath02203312007-06-11 22:06:31 +00001639 else
1640 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001641 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001643#ifdef __WALL
1644 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1645 if (errno == ECHILD) /* Already gone. */
1646 break;
1647 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001648 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001649 break;
1650 }
1651#endif /* __WALL */
1652 /* No __WALL here. */
1653 if (waitpid(tcp->pid, &status, 0) < 0) {
1654 if (errno != ECHILD) {
1655 perror("detach: waiting");
1656 break;
1657 }
1658#ifdef __WCLONE
1659 /* If no processes, try clones. */
1660 if (wait4(tcp->pid, &status, __WCLONE,
1661 NULL) < 0) {
1662 if (errno != ECHILD)
1663 perror("detach: waiting");
1664 break;
1665 }
1666#endif /* __WCLONE */
1667 }
1668#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001669 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001670#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671 if (!WIFSTOPPED(status)) {
1672 /* Au revoir, mon ami. */
1673 break;
1674 }
1675 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001676 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 break;
1678 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001679 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001680 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001681 : WSTOPSIG(status));
1682 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001685 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001686#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687
1688#if defined(SUNOS4)
1689 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1690 if (sig && kill(tcp->pid, sig) < 0)
1691 perror("detach: kill");
1692 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001693 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694#endif /* SUNOS4 */
1695
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696 if (!qflag)
1697 fprintf(stderr, "Process %u detached\n", tcp->pid);
1698
1699 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001700
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701 return error;
1702}
1703
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001704#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001706static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707{
1708 int pid;
1709 int status;
1710
1711 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 }
1713}
1714
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001715#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716
1717static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001718cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719{
1720 int i;
1721 struct tcb *tcp;
1722
Roland McGrathee9d4352002-12-18 04:16:10 +00001723 for (i = 0; i < tcbtabsize; i++) {
1724 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725 if (!(tcp->flags & TCB_INUSE))
1726 continue;
1727 if (debug)
1728 fprintf(stderr,
1729 "cleanup: looking at pid %u\n", tcp->pid);
1730 if (tcp_last &&
1731 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001732 tprintf(" <unfinished ...>");
1733 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 }
1735 if (tcp->flags & TCB_ATTACHED)
1736 detach(tcp, 0);
1737 else {
1738 kill(tcp->pid, SIGCONT);
1739 kill(tcp->pid, SIGTERM);
1740 }
1741 }
1742 if (cflag)
1743 call_summary(outf);
1744}
1745
1746static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001747interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748{
1749 interrupted = 1;
1750}
1751
1752#ifndef HAVE_STRERROR
1753
Roland McGrath6d2b3492002-12-30 00:51:30 +00001754#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755extern int sys_nerr;
1756extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001757#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
1759const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001760strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761{
1762 static char buf[64];
1763
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001764 if (err_no < 1 || err_no >= sys_nerr) {
1765 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766 return buf;
1767 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001768 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769}
1770
1771#endif /* HAVE_STERRROR */
1772
1773#ifndef HAVE_STRSIGNAL
1774
Roland McGrath8f474e02003-01-14 07:53:33 +00001775#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001776extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001778#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1779extern char *_sys_siglist[];
1780#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781
1782const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001783strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784{
1785 static char buf[64];
1786
1787 if (sig < 1 || sig >= NSIG) {
1788 sprintf(buf, "Unknown signal %d", sig);
1789 return buf;
1790 }
1791#ifdef HAVE__SYS_SIGLIST
1792 return _sys_siglist[sig];
1793#else
1794 return sys_siglist[sig];
1795#endif
1796}
1797
1798#endif /* HAVE_STRSIGNAL */
1799
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001800#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001801
1802static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001803rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804{
1805 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806
Roland McGrathee9d4352002-12-18 04:16:10 +00001807 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001808 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001809 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001810 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001811 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001812 }
1813
Roland McGrathca16be82003-01-10 19:55:28 +00001814 for (i = j = 0; i < tcbtabsize; i++) {
1815 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816 if (!(tcp->flags & TCB_INUSE))
1817 continue;
1818 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001819 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820 j++;
1821 }
1822 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001823 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824 }
1825}
1826
1827#ifndef HAVE_POLLABLE_PROCFS
1828
1829static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001830proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001831{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832 int i;
1833
1834 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001835 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836 }
1837 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001838 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839 }
1840}
1841
1842static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001843proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844{
1845 int i;
1846 int n;
1847 struct proc_pollfd pollinfo;
1848
1849 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1850 return n;
1851 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001852 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853 }
1854 for (i = 0; i < nprocs; i++) {
1855 if (pollv[i].fd == pollinfo.fd)
1856 pollv[i].revents = pollinfo.revents;
1857 else
1858 pollv[i].revents = 0;
1859 }
1860 poller_pid = pollinfo.pid;
1861 return 1;
1862}
1863
1864static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001865wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866{
1867}
1868
1869static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001870proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871{
1872 struct proc_pollfd pollinfo;
1873 struct sigaction sa;
1874 sigset_t blocked_set, empty_set;
1875 int i;
1876 int n;
1877 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001878#ifdef FREEBSD
1879 struct procfs_status pfs;
1880#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001881
1882 switch (fork()) {
1883 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001884 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885 case 0:
1886 break;
1887 default:
1888 return;
1889 }
1890
1891 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1892 sa.sa_flags = 0;
1893 sigemptyset(&sa.sa_mask);
1894 sigaction(SIGHUP, &sa, NULL);
1895 sigaction(SIGINT, &sa, NULL);
1896 sigaction(SIGQUIT, &sa, NULL);
1897 sigaction(SIGPIPE, &sa, NULL);
1898 sigaction(SIGTERM, &sa, NULL);
1899 sa.sa_handler = wakeup_handler;
1900 sigaction(SIGUSR1, &sa, NULL);
1901 sigemptyset(&blocked_set);
1902 sigaddset(&blocked_set, SIGUSR1);
1903 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1904 sigemptyset(&empty_set);
1905
1906 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001907 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001908 }
1909 n = rl.rlim_cur;
1910 for (i = 0; i < n; i++) {
1911 if (i != pfd && i != proc_poll_pipe[1])
1912 close(i);
1913 }
1914
1915 pollinfo.fd = pfd;
1916 pollinfo.pid = getpid();
1917 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001918#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001919 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1920#else
1921 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1922#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001923 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 switch (errno) {
1925 case EINTR:
1926 continue;
1927 case EBADF:
1928 pollinfo.revents = POLLERR;
1929 break;
1930 case ENOENT:
1931 pollinfo.revents = POLLHUP;
1932 break;
1933 default:
1934 perror("proc_poller: PIOCWSTOP");
1935 }
1936 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1937 _exit(0);
1938 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001939 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1941 sigsuspend(&empty_set);
1942 }
1943}
1944
1945#endif /* !HAVE_POLLABLE_PROCFS */
1946
1947static int
1948choose_pfd()
1949{
1950 int i, j;
1951 struct tcb *tcp;
1952
1953 static int last;
1954
1955 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001956 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 /*
1958 * The previous process is ready to run again. We'll
1959 * let it do so if it is currently in a syscall. This
1960 * heuristic improves the readability of the trace.
1961 */
1962 tcp = pfd2tcb(pollv[last].fd);
1963 if (tcp && (tcp->flags & TCB_INSYSCALL))
1964 return pollv[last].fd;
1965 }
1966
1967 for (i = 0; i < nprocs; i++) {
1968 /* Let competing children run round robin. */
1969 j = (i + last + 1) % nprocs;
1970 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1971 tcp = pfd2tcb(pollv[j].fd);
1972 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001973 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001974 }
1975 droptcb(tcp);
1976 return -1;
1977 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001978 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001979 last = j;
1980 return pollv[j].fd;
1981 }
1982 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001983 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984}
1985
1986static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001987trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001988{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001989#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00001990 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00001991#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001992 struct tcb *tcp;
1993 int pfd;
1994 int what;
1995 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001996 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997
1998 for (;;) {
1999 if (interactive)
2000 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2001
2002 if (nprocs == 0)
2003 break;
2004
2005 switch (nprocs) {
2006 case 1:
2007#ifndef HAVE_POLLABLE_PROCFS
2008 if (proc_poll_pipe[0] == -1) {
2009#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002010 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 if (!tcp)
2012 continue;
2013 pfd = tcp->pfd;
2014 if (pfd == -1)
2015 continue;
2016 break;
2017#ifndef HAVE_POLLABLE_PROCFS
2018 }
2019 /* fall through ... */
2020#endif /* !HAVE_POLLABLE_PROCFS */
2021 default:
2022#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002023#ifdef POLL_HACK
2024 /* On some systems (e.g. UnixWare) we get too much ugly
2025 "unfinished..." stuff when multiple proceses are in
2026 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002027
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002028 if (in_syscall) {
2029 struct pollfd pv;
2030 tcp = in_syscall;
2031 in_syscall = NULL;
2032 pv.fd = tcp->pfd;
2033 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002034 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002035 if (interrupted)
2036 return 0;
2037 continue;
2038 }
2039 else if (what == 1 && pv.revents & POLLWANT) {
2040 goto FOUND;
2041 }
2042 }
2043#endif
2044
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045 if (poll(pollv, nprocs, INFTIM) < 0) {
2046 if (interrupted)
2047 return 0;
2048 continue;
2049 }
2050#else /* !HAVE_POLLABLE_PROCFS */
2051 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2052 if (interrupted)
2053 return 0;
2054 continue;
2055 }
2056#endif /* !HAVE_POLLABLE_PROCFS */
2057 pfd = choose_pfd();
2058 if (pfd == -1)
2059 continue;
2060 break;
2061 }
2062
2063 /* Look up `pfd' in our table. */
2064 if ((tcp = pfd2tcb(pfd)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002065 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002066 }
John Hughesb6643082002-05-23 11:02:22 +00002067#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002068 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002069#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 /* Get the status of the process. */
2071 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002072#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002073 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002074#else /* FREEBSD */
2075 /* Thanks to some scheduling mystery, the first poller
2076 sometimes waits for the already processed end of fork
2077 event. Doing a non blocking poll here solves the problem. */
2078 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002079 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002080 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002081 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002082#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083 ioctl_errno = errno;
2084#ifndef HAVE_POLLABLE_PROCFS
2085 if (proc_poll_pipe[0] != -1) {
2086 if (ioctl_result < 0)
2087 kill(poller_pid, SIGKILL);
2088 else
2089 kill(poller_pid, SIGUSR1);
2090 }
2091#endif /* !HAVE_POLLABLE_PROCFS */
2092 }
2093 if (interrupted)
2094 return 0;
2095
2096 if (interactive)
2097 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2098
2099 if (ioctl_result < 0) {
2100 /* Find out what happened if it failed. */
2101 switch (ioctl_errno) {
2102 case EINTR:
2103 case EBADF:
2104 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002105#ifdef FREEBSD
2106 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002107#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002108 case ENOENT:
2109 droptcb(tcp);
2110 continue;
2111 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002112 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113 }
2114 }
2115
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002116#ifdef FREEBSD
2117 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2118 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002119 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002120 continue;
2121 }
Roland McGrath553a6092002-12-16 20:40:39 +00002122#endif
2123
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002124 /* clear the just started flag */
2125 tcp->flags &= ~TCB_STARTUP;
2126
2127 /* set current output file */
2128 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002129 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002130
2131 if (cflag) {
2132 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002133#ifdef FREEBSD
2134 char buf[1024];
2135 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002136
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002137 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2138 buf[len] = '\0';
2139 sscanf(buf,
2140 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2141 &stime.tv_sec, &stime.tv_usec);
2142 } else
2143 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002144#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2146 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002147#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2149 tcp->stime = stime;
2150 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002151 what = tcp->status.PR_WHAT;
2152 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002153#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002155 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2156 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002158 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002159 }
2160 }
2161 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002162#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002164#ifdef POLL_HACK
2165 in_syscall = tcp;
2166#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002167 case PR_SYSEXIT:
2168 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002169 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 }
2171 break;
2172 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002173 if (cflag != CFLAG_ONLY_STATS
2174 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002175 printleader(tcp);
2176 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002177 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002178 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002179#ifdef PR_INFO
2180 if (tcp->status.PR_INFO.si_signo == what) {
2181 printleader(tcp);
2182 tprintf(" siginfo=");
2183 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002184 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002185 }
2186#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 }
2188 break;
2189 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002190 if (cflag != CFLAGS_ONLY_STATS
2191 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192 printleader(tcp);
2193 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002194 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 }
2196 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002197#ifdef FREEBSD
2198 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002199 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002200#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002202 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 break;
2204 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002205 /* Remember current print column before continuing. */
2206 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002207 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002208#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002209 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002210#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002211 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002212#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002213 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002214 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002215 }
2216 }
2217 return 0;
2218}
2219
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002220#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221
Roland McGratheb9e2e82009-06-02 16:49:22 -07002222static int
2223trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224{
2225 int pid;
2226 int wait_errno;
2227 int status;
2228 struct tcb *tcp;
2229#ifdef LINUX
2230 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002231 struct rusage *rup = cflag ? &ru : NULL;
2232# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002233 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002234# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002235#endif /* LINUX */
2236
Roland McGratheb9e2e82009-06-02 16:49:22 -07002237 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002238 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002239 return 0;
2240 if (interactive)
2241 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002242#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002243# ifdef __WALL
2244 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002245 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002246 /* this kernel does not support __WALL */
2247 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002248 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002249 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002250 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002251 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002252 pid = wait4(-1, &status, __WCLONE, rup);
2253 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002254 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002255 }
2256 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002257# else
2258 pid = wait4(-1, &status, 0, rup);
2259# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002260#endif /* LINUX */
2261#ifdef SUNOS4
2262 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002265 if (interactive)
2266 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002268 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002269 switch (wait_errno) {
2270 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002271 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002272 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002273 /*
2274 * We would like to verify this case
2275 * but sometimes a race in Solbourne's
2276 * version of SunOS sometimes reports
2277 * ECHILD before sending us SIGCHILD.
2278 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002279 return 0;
2280 default:
2281 errno = wait_errno;
2282 perror("strace: wait");
2283 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002284 }
2285 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002286 if (pid == popen_pid) {
2287 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002288 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002289 continue;
2290 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002291 if (debug) {
2292 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2293#ifdef LINUX
2294 unsigned ev = (unsigned)status >> 16;
2295 if (ev) {
2296 static const char *const event_names[] = {
2297 [PTRACE_EVENT_CLONE] = "CLONE",
2298 [PTRACE_EVENT_FORK] = "FORK",
2299 [PTRACE_EVENT_VFORK] = "VFORK",
2300 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2301 [PTRACE_EVENT_EXEC] = "EXEC",
2302 [PTRACE_EVENT_EXIT] = "EXIT",
2303 };
2304 const char *e;
2305 if (ev < ARRAY_SIZE(event_names))
2306 e = event_names[ev];
2307 else {
2308 sprintf(buf, "?? (%u)", ev);
2309 e = buf;
2310 }
2311 fprintf(stderr, " PTRACE_EVENT_%s", e);
2312 }
2313#endif
2314 strcpy(buf, "???");
2315 if (WIFSIGNALED(status))
2316#ifdef WCOREDUMP
2317 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2318 WCOREDUMP(status) ? "core," : "",
2319 signame(WTERMSIG(status)));
2320#else
2321 sprintf(buf, "WIFSIGNALED,sig=%s",
2322 signame(WTERMSIG(status)));
2323#endif
2324 if (WIFEXITED(status))
2325 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2326 if (WIFSTOPPED(status))
2327 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002328#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002329 if (WIFCONTINUED(status))
2330 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002331#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002332 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2333 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334
2335 /* Look up `pid' in our table. */
2336 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002337#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002338 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002339 /* This is needed to go with the CLONE_PTRACE
2340 changes in process.c/util.c: we might see
2341 the child's initial trap before we see the
2342 parent return from the clone syscall.
2343 Leave the child suspended until the parent
2344 returns from its system call. Only then
2345 will we have the association of parent and
2346 child so that we know how to do clearbpt
2347 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002348 tcp = alloctcb(pid);
Denys Vlasenko833fb132011-08-17 11:30:56 +02002349 tcp->flags |= TCB_ATTACHED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002350 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002351 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002352 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002353 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002354 else
2355 /* This can happen if a clone call used
2356 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002357#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002358 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002359 if (WIFSTOPPED(status))
2360 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002361 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002362 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002364 /* set current output file */
2365 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002366 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002367#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002368 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002369 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2370 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002371 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002372#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002373
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002374 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002375 if (pid == strace_child)
2376 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002377 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002378 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2379 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002380#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002381 tprintf("+++ killed by %s %s+++",
2382 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002383 WCOREDUMP(status) ? "(core dumped) " : "");
2384#else
2385 tprintf("+++ killed by %s +++",
2386 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002387#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002388 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002389 }
2390 droptcb(tcp);
2391 continue;
2392 }
2393 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002394 if (pid == strace_child)
2395 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002396 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002397 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002398 tprintf(" <unfinished ... exit status %d>\n",
2399 WEXITSTATUS(status));
2400 tcp_last = NULL;
2401 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002402 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2403 printleader(tcp);
2404 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2405 printtrailer();
2406 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002407 droptcb(tcp);
2408 continue;
2409 }
2410 if (!WIFSTOPPED(status)) {
2411 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2412 droptcb(tcp);
2413 continue;
2414 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002416 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002417 /* Ptrace event (we ignore all of them for now) */
2418 goto tracing;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002419 }
2420
Roland McGrath02203312007-06-11 22:06:31 +00002421 /*
2422 * Interestingly, the process may stop
2423 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002424 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002425 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002426 * A no-MMU vforked child won't send up a signal,
2427 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002428 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002429 if ((tcp->flags & TCB_STARTUP) &&
2430 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002431 /*
2432 * This flag is there to keep us in sync.
2433 * Next time this process stops it should
2434 * really be entering a system call.
2435 */
2436 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002437 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002438 /*
2439 * One example is a breakpoint inherited from
2440 * parent through fork ().
2441 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2443 droptcb(tcp);
2444 cleanup();
2445 return -1;
2446 }
2447 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002448#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002449 if (ptrace_setoptions) {
2450 if (debug)
2451 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2452 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2453 if (errno != ESRCH) {
2454 /* Should never happen, really */
2455 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002456 }
2457 }
2458 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002459#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002460 goto tracing;
2461 }
2462
Denys Vlasenko75422762011-05-27 14:36:01 +02002463 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002464 if (WSTOPSIG(status) == SIGSTOP &&
2465 (tcp->flags & TCB_SIGTRAPPED)) {
2466 /*
2467 * Trapped attempt to block SIGTRAP
2468 * Hope we are back in control now.
2469 */
2470 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002471 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 cleanup();
2473 return -1;
2474 }
2475 continue;
2476 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002477 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002479 siginfo_t si;
2480#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002481 long pc = 0;
2482 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002483
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002484 upeek(tcp, PT_CR_IPSR, &psr);
2485 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002486
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002487# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002488 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002489# define PC_FORMAT_STR " @ %lx"
2490# define PC_FORMAT_ARG pc
2491#else
2492# define PC_FORMAT_STR "%s"
2493# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002494#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002496 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2497 tprintf("--- ");
2498 printsiginfo(&si, verbose(tcp));
2499 tprintf(" (%s)" PC_FORMAT_STR " ---",
2500 strsignal(WSTOPSIG(status)),
2501 PC_FORMAT_ARG);
2502 } else
2503 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2504 strsignal(WSTOPSIG(status)),
2505 signame(WSTOPSIG(status)),
2506 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002507 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002508 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002509 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510 cleanup();
2511 return -1;
2512 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513 continue;
2514 }
Roland McGrath02203312007-06-11 22:06:31 +00002515 /* we handled the STATUS, we are permitted to interrupt now. */
2516 if (interrupted)
2517 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002518 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2519 /* ptrace() failed in trace_syscall() with ESRCH.
2520 * Likely a result of process disappearing mid-flight.
2521 * Observed case: exit_group() terminating
2522 * all processes in thread group. In this case, threads
2523 * "disappear" in an unpredictable moment without any
2524 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002525 */
2526 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002527 if (tcp_last) {
2528 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002529 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002530 */
2531 tcp_last->flags |= TCB_REPRINT;
2532 tprintf(" <unfinished ...>");
2533 printtrailer();
2534 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002535 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002536 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002537 ptrace(PTRACE_KILL,
2538 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 droptcb(tcp);
2540 }
2541 continue;
2542 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002544 /* Remember current print column before continuing. */
2545 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002546 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002547 cleanup();
2548 return -1;
2549 }
2550 }
2551 return 0;
2552}
2553
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002554#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002555
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002556void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002557tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002558{
2559 va_list args;
2560
Andreas Schwabe5355de2009-10-27 16:56:43 +01002561 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002562 if (outf) {
2563 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002564 if (n < 0) {
2565 if (outf != stderr)
2566 perror(outfname == NULL
2567 ? "<writing to pipe>" : outfname);
2568 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002569 curcol += n;
2570 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002571 va_end(args);
2572 return;
2573}
2574
2575void
Denys Vlasenko12014262011-05-30 14:00:14 +02002576printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002578 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002579 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002580 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002581 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002582 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002583 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002584 tprintf("= ? <unavailable>\n");
2585 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002586 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002587 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002588 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002589 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002590 }
2591 curcol = 0;
2592 if ((followfork == 1 || pflag_seen > 1) && outfname)
2593 tprintf("%-5d ", tcp->pid);
2594 else if (nprocs > 1 && !outfname)
2595 tprintf("[pid %5u] ", tcp->pid);
2596 if (tflag) {
2597 char str[sizeof("HH:MM:SS")];
2598 struct timeval tv, dtv;
2599 static struct timeval otv;
2600
2601 gettimeofday(&tv, NULL);
2602 if (rflag) {
2603 if (otv.tv_sec == 0)
2604 otv = tv;
2605 tv_sub(&dtv, &tv, &otv);
2606 tprintf("%6ld.%06ld ",
2607 (long) dtv.tv_sec, (long) dtv.tv_usec);
2608 otv = tv;
2609 }
2610 else if (tflag > 2) {
2611 tprintf("%ld.%06ld ",
2612 (long) tv.tv_sec, (long) tv.tv_usec);
2613 }
2614 else {
2615 time_t local = tv.tv_sec;
2616 strftime(str, sizeof(str), "%T", localtime(&local));
2617 if (tflag > 1)
2618 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2619 else
2620 tprintf("%s ", str);
2621 }
2622 }
2623 if (iflag)
2624 printcall(tcp);
2625}
2626
2627void
Denys Vlasenko12014262011-05-30 14:00:14 +02002628tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629{
2630 if (curcol < col)
2631 tprintf("%*s", col - curcol, "");
2632}
2633
2634void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002635printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636{
2637 tprintf("\n");
2638 tcp_last = NULL;
2639}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002640
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002641#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002642
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002643int
2644mp_ioctl(int fd, int cmd, void *arg, int size)
2645{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002646 struct iovec iov[2];
2647 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002648
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002649 iov[0].iov_base = &cmd;
2650 iov[0].iov_len = sizeof cmd;
2651 if (arg) {
2652 ++n;
2653 iov[1].iov_base = arg;
2654 iov[1].iov_len = size;
2655 }
Roland McGrath553a6092002-12-16 20:40:39 +00002656
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002657 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002658}
2659
2660#endif