blob: 61d012164cdb6028d748045001109096e70e76fd [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
52# if defined __NR_tgkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020053# define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# elif defined __NR_tkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020055# define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000056# else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenkob63256e2011-06-07 12:13:24 +020061# define my_tgkill(pid, tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000062# endif
63#endif
64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000065#if defined(IA64) && defined(LINUX)
66# include <asm/ptrace_offsets.h>
67#endif
68
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000069#ifdef USE_PROCFS
70#include <poll.h>
71#endif
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#ifdef SVR4
74#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000075#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000076#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#include <sys/uio.h>
78#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000080#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000082extern int optind;
83extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085
Roland McGrath41c48222008-07-18 00:25:10 +000086int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020087unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020088/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020089static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000090int dtime = 0, xflag = 0, qflag = 0;
91cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000092static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000093/*
94 * daemonized_tracer supports -D option.
95 * With this option, strace forks twice.
96 * Unlike normal case, with -D *grandparent* process exec's,
97 * becoming a traced process. Child exits (this prevents traced process
98 * from having children it doesn't expect to have), and grandchild
99 * attaches to grandparent similarly to strace -p PID.
100 * This allows for more transparent interaction in cases
101 * when process and its parent are communicating via signals,
102 * wait() etc. Without -D, strace process gets lodged in between,
103 * disrupting parent<->child link.
104 */
105static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000107/* Sometimes we want to print only succeeding syscalls. */
108int not_failing_only = 0;
109
Grant Edwards8a082772011-04-07 20:25:40 +0000110/* Show path associated with fd arguments */
111int show_fd_path = 0;
112
113/* are we filtering traces based on paths? */
114int tracing_paths = 0;
115
Dmitry V. Levina6809652008-11-10 17:14:58 +0000116static int exit_code = 0;
117static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200118static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000120static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121uid_t run_uid;
122gid_t run_gid;
123
124int acolumn = DEFAULT_ACOLUMN;
125int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000129struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200130static unsigned int nprocs, tcbtabsize;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000131const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Andreas Schwabe5355de2009-10-27 16:56:43 +0100133static int detach(struct tcb *tcp, int sig);
134static int trace(void);
135static void cleanup(void);
136static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137static sigset_t empty_set, blocked_set;
138
139#ifdef HAVE_SIG_ATOMIC_T
140static volatile sig_atomic_t interrupted;
141#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143#endif /* !HAVE_SIG_ATOMIC_T */
144
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000145#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
Andreas Schwabe5355de2009-10-27 16:56:43 +0100147static struct tcb *pfd2tcb(int pfd);
148static void reaper(int sig);
149static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000150static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#ifndef HAVE_POLLABLE_PROCFS
153
Andreas Schwabe5355de2009-10-27 16:56:43 +0100154static void proc_poll_open(void);
155static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156
157struct proc_pollfd {
158 int fd;
159 int revents;
160 int pid;
161};
162
163static int poller_pid;
164static int proc_poll_pipe[2] = { -1, -1 };
165
166#endif /* !HAVE_POLLABLE_PROCFS */
167
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000168#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000169#define POLLWANT POLLWRNORM
170#else
171#define POLLWANT POLLPRI
172#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000173#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174
175static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200176usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000177{
178 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000179usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000180 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000181 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200182 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000183 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200185-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186-f -- follow forks, -ff -- with output into separate files\n\
187-F -- attempt to follow vforks, -h -- print help message\n\
188-i -- print instruction pointer at time of syscall\n\
189-q -- suppress messages about attaching, detaching, etc.\n\
190-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
191-T -- print time spent in each syscall, -V -- print version\n\
192-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
193-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000194-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195-a column -- alignment COLUMN for printing syscall results (default %d)\n\
196-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
197 options: trace, abbrev, verbose, raw, signal, read, or write\n\
198-o file -- send trace output to FILE instead of stderr\n\
199-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
200-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000201-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
203-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
204-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000205-E var=val -- put var=val in the environment for command\n\
206-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000207-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000209-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000210 */
211, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000212 exit(exitval);
213}
214
Denys Vlasenko75422762011-05-27 14:36:01 +0200215static void die(void) __attribute__ ((noreturn));
216static void die(void)
217{
218 if (strace_tracer_pid == getpid()) {
219 cflag = 0;
220 cleanup();
221 }
222 exit(1);
223}
224
225static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200226{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000227 fflush(NULL);
228 fprintf(stderr, "%s: ", progname);
229 vfprintf(stderr, fmt, p);
230 if (err_no)
231 fprintf(stderr, ": %s\n", strerror(err_no));
232 else
233 putc('\n', stderr);
234 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200235}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200236
Denys Vlasenko75422762011-05-27 14:36:01 +0200237void error_msg(const char *fmt, ...)
238{
239 va_list p;
240 va_start(p, fmt);
241 verror_msg(0, fmt, p);
242 va_end(p);
243}
244
245void error_msg_and_die(const char *fmt, ...)
246{
247 va_list p;
248 va_start(p, fmt);
249 verror_msg(0, fmt, p);
250 die();
251}
252
253void perror_msg(const char *fmt, ...)
254{
255 va_list p;
256 va_start(p, fmt);
257 verror_msg(errno, fmt, p);
258 va_end(p);
259}
260
261void perror_msg_and_die(const char *fmt, ...)
262{
263 va_list p;
264 va_start(p, fmt);
265 verror_msg(errno, fmt, p);
266 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200267}
268
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269#ifdef SVR4
270#ifdef MIPS
271void
272foobar()
273{
274}
275#endif /* MIPS */
276#endif /* SVR4 */
277
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400278/* Glue for systems without a MMU that cannot provide fork() */
279#ifdef HAVE_FORK
280# define strace_vforked 0
281#else
282# define strace_vforked 1
283# define fork() vfork()
284#endif
285
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200286static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000287set_cloexec_flag(int fd)
288{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200289 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000290
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200291 flags = fcntl(fd, F_GETFD);
292 if (flags < 0) {
293 /* Can happen only if fd is bad.
294 * Should never happen: if it does, we have a bug
295 * in the caller. Therefore we just abort
296 * instead of propagating the error.
297 */
298 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000299 }
300
301 newflags = flags | FD_CLOEXEC;
302 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200303 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000304
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200305 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000306}
307
308/*
309 * When strace is setuid executable, we have to swap uids
310 * before and after filesystem and process management operations.
311 */
312static void
313swap_uid(void)
314{
315#ifndef SVR4
316 int euid = geteuid(), uid = getuid();
317
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200318 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200319 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000320 }
321#endif
322}
323
Roland McGrath4bfa6262007-07-05 20:03:16 +0000324#if _LFS64_LARGEFILE
325# define fopen_for_output fopen64
326#else
327# define fopen_for_output fopen
328#endif
329
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200331strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000332{
333 FILE *fp;
334
335 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200336 fp = fopen_for_output(path, "w");
337 if (!fp)
338 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000339 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200340 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000341 return fp;
342}
343
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200344static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000345
346#ifndef _PATH_BSHELL
347# define _PATH_BSHELL "/bin/sh"
348#endif
349
350/*
351 * We cannot use standard popen(3) here because we have to distinguish
352 * popen child process from other processes we trace, and standard popen(3)
353 * does not export its child's pid.
354 */
355static FILE *
356strace_popen(const char *command)
357{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200358 FILE *fp;
359 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360
361 swap_uid();
362 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200363 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200365 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000366
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200367 popen_pid = vfork();
368 if (popen_pid == -1)
369 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200371 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000372 /* child */
373 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200374 if (fds[0] != 0) {
375 if (dup2(fds[0], 0))
376 perror_msg_and_die("dup2");
377 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000378 }
379 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200380 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000381 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200382
383 /* parent */
384 close(fds[0]);
385 swap_uid();
386 fp = fdopen(fds[1], "w");
387 if (!fp)
388 error_msg_and_die("Out of memory");
389 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000390}
391
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200392static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000393newoutf(struct tcb *tcp)
394{
395 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000396 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000397 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200398 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000399 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400}
401
Roland McGrath02203312007-06-11 22:06:31 +0000402static void
403startup_attach(void)
404{
405 int tcbi;
406 struct tcb *tcp;
407
408 /*
409 * Block user interruptions as we would leave the traced
410 * process stopped (process state T) if we would terminate in
411 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200412 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000413 */
414 if (interactive)
415 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
416
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000417 if (daemonized_tracer) {
418 pid_t pid = fork();
419 if (pid < 0) {
420 _exit(1);
421 }
422 if (pid) { /* parent */
423 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200424 * Wait for grandchild to attach to straced process
425 * (grandparent). Grandchild SIGKILLs us after it attached.
426 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000427 * it proceeds to exec the straced program.
428 */
429 pause();
430 _exit(0); /* paranoia */
431 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200432 /* grandchild */
433 /* We will be the tracer process. Remember our new pid: */
434 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000435 }
436
Roland McGrath02203312007-06-11 22:06:31 +0000437 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
438 tcp = tcbtab[tcbi];
439 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
440 continue;
441#ifdef LINUX
442 if (tcp->flags & TCB_CLONE_THREAD)
443 continue;
444#endif
445 /* Reinitialize the output since it may have changed. */
446 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200447 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000448
449#ifdef USE_PROCFS
450 if (proc_open(tcp, 1) < 0) {
451 fprintf(stderr, "trouble opening proc file\n");
452 droptcb(tcp);
453 continue;
454 }
455#else /* !USE_PROCFS */
456# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000457 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000458 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000459 DIR *dir;
460
461 sprintf(procdir, "/proc/%d/task", tcp->pid);
462 dir = opendir(procdir);
463 if (dir != NULL) {
464 unsigned int ntid = 0, nerr = 0;
465 struct dirent *de;
466 int tid;
467 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000468 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000469 continue;
470 tid = atoi(de->d_name);
471 if (tid <= 0)
472 continue;
473 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000474 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000475 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000476 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000477 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800478 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000479 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000480 tcp->parent = tcbtab[tcbi];
481 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000482 if (interactive) {
483 sigprocmask(SIG_SETMASK, &empty_set, NULL);
484 if (interrupted)
485 return;
486 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
487 }
Roland McGrath02203312007-06-11 22:06:31 +0000488 }
489 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000490 ntid -= nerr;
491 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000492 perror("attach: ptrace(PTRACE_ATTACH, ...)");
493 droptcb(tcp);
494 continue;
495 }
496 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000497 fprintf(stderr, ntid > 1
498? "Process %u attached with %u threads - interrupt to quit\n"
499: "Process %u attached - interrupt to quit\n",
500 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000501 }
502 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000503 } /* if (opendir worked) */
504 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000505# endif
506 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
507 perror("attach: ptrace(PTRACE_ATTACH, ...)");
508 droptcb(tcp);
509 continue;
510 }
511 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000512
513 if (daemonized_tracer) {
514 /*
515 * It is our grandparent we trace, not a -p PID.
516 * Don't want to just detach on exit, so...
517 */
518 tcp->flags &= ~TCB_ATTACHED;
519 /*
520 * Make parent go away.
521 * Also makes grandparent's wait() unblock.
522 */
523 kill(getppid(), SIGKILL);
524 }
525
Roland McGrath02203312007-06-11 22:06:31 +0000526#endif /* !USE_PROCFS */
527 if (!qflag)
528 fprintf(stderr,
529 "Process %u attached - interrupt to quit\n",
530 tcp->pid);
531 }
532
533 if (interactive)
534 sigprocmask(SIG_SETMASK, &empty_set, NULL);
535}
536
537static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200538startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000539{
540 struct stat statbuf;
541 const char *filename;
542 char pathname[MAXPATHLEN];
543 int pid = 0;
544 struct tcb *tcp;
545
546 filename = argv[0];
547 if (strchr(filename, '/')) {
548 if (strlen(filename) > sizeof pathname - 1) {
549 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200550 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000551 }
552 strcpy(pathname, filename);
553 }
554#ifdef USE_DEBUGGING_EXEC
555 /*
556 * Debuggers customarily check the current directory
557 * first regardless of the path but doing that gives
558 * security geeks a panic attack.
559 */
560 else if (stat(filename, &statbuf) == 0)
561 strcpy(pathname, filename);
562#endif /* USE_DEBUGGING_EXEC */
563 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000564 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000565 int m, n, len;
566
567 for (path = getenv("PATH"); path && *path; path += m) {
568 if (strchr(path, ':')) {
569 n = strchr(path, ':') - path;
570 m = n + 1;
571 }
572 else
573 m = n = strlen(path);
574 if (n == 0) {
575 if (!getcwd(pathname, MAXPATHLEN))
576 continue;
577 len = strlen(pathname);
578 }
579 else if (n > sizeof pathname - 1)
580 continue;
581 else {
582 strncpy(pathname, path, n);
583 len = n;
584 }
585 if (len && pathname[len - 1] != '/')
586 pathname[len++] = '/';
587 strcpy(pathname + len, filename);
588 if (stat(pathname, &statbuf) == 0 &&
589 /* Accept only regular files
590 with some execute bits set.
591 XXX not perfect, might still fail */
592 S_ISREG(statbuf.st_mode) &&
593 (statbuf.st_mode & 0111))
594 break;
595 }
596 }
597 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200598 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000599 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000600 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000601 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200602 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000603 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200604 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
605 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000606 ) {
607 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000608#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200609 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000610#ifdef MIPS
611 /* Kludge for SGI, see proc_open for details. */
612 sa.sa_handler = foobar;
613 sa.sa_flags = 0;
614 sigemptyset(&sa.sa_mask);
615 sigaction(SIGINT, &sa, NULL);
616#endif /* MIPS */
617#ifndef FREEBSD
618 pause();
619#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000620 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000621#endif /* FREEBSD */
622#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200623 if (outf != stderr)
624 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000625
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000626 if (!daemonized_tracer) {
627 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200628 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000629 }
630 if (debug)
631 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000632 }
Roland McGrath02203312007-06-11 22:06:31 +0000633
634 if (username != NULL || geteuid() == 0) {
635 uid_t run_euid = run_uid;
636 gid_t run_egid = run_gid;
637
638 if (statbuf.st_mode & S_ISUID)
639 run_euid = statbuf.st_uid;
640 if (statbuf.st_mode & S_ISGID)
641 run_egid = statbuf.st_gid;
642
643 /*
644 * It is important to set groups before we
645 * lose privileges on setuid.
646 */
647 if (username != NULL) {
648 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200649 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000650 }
651 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200652 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000653 }
654 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200655 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000656 }
657 }
658 }
659 else
660 setreuid(run_uid, run_uid);
661
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000662 if (!daemonized_tracer) {
663 /*
664 * Induce an immediate stop so that the parent
665 * will resume us with PTRACE_SYSCALL and display
666 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400667 * Unless of course we're on a no-MMU system where
668 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000669 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400670 if (!strace_vforked)
671 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672 } else {
673 struct sigaction sv_sigchld;
674 sigaction(SIGCHLD, NULL, &sv_sigchld);
675 /*
676 * Make sure it is not SIG_IGN, otherwise wait
677 * will not block.
678 */
679 signal(SIGCHLD, SIG_DFL);
680 /*
681 * Wait for grandchild to attach to us.
682 * It kills child after that, and wait() unblocks.
683 */
684 alarm(3);
685 wait(NULL);
686 alarm(0);
687 sigaction(SIGCHLD, &sv_sigchld, NULL);
688 }
Roland McGrath02203312007-06-11 22:06:31 +0000689#endif /* !USE_PROCFS */
690
691 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200692 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000693 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000694
695 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200696 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
697 strace_tracer_pid = getpid();
698
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000699 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000700 if (daemonized_tracer) {
701 /* We want subsequent startup_attach() to attach to it. */
702 tcp->flags |= TCB_ATTACHED;
703 }
Roland McGrath02203312007-06-11 22:06:31 +0000704#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000705 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200706 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000707 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000709}
710
Wang Chaob13c0de2010-11-12 17:25:19 +0800711#ifdef LINUX
712/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000713 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800714 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000715 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800716 */
717static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200718test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800719{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000720 int pid, expected_grandchild = 0, found_grandchild = 0;
721 const unsigned int test_options = PTRACE_O_TRACECLONE |
722 PTRACE_O_TRACEFORK |
723 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800724
725 if ((pid = fork()) < 0)
726 return -1;
727 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000728 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800729 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800730 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000731 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800732 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000733
734 while (1) {
735 int status, tracee_pid;
736
737 tracee_pid = wait(&status);
738 if (tracee_pid == -1) {
739 if (errno == EINTR)
740 continue;
741 else if (errno == ECHILD)
742 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200743 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000744 return -1;
745 }
746 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000747 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000748 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
749 errno != ESRCH)
750 kill(tracee_pid, SIGKILL);
751 }
752 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000753 switch (WSTOPSIG(status)) {
754 case SIGSTOP:
755 if (ptrace(PTRACE_SETOPTIONS, pid,
756 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000757 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800758 return -1;
759 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000760 break;
761 case SIGTRAP:
762 if (status >> 16 == PTRACE_EVENT_FORK) {
763 long msg = 0;
764
765 if (ptrace(PTRACE_GETEVENTMSG, pid,
766 NULL, (long) &msg) == 0)
767 expected_grandchild = msg;
768 }
769 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800770 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000771 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
772 errno != ESRCH)
773 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800774 }
775 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000776 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200777 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800778 return 0;
779}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200780
781/*
782 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
783 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
784 * and then see whether it will stop with (SIGTRAP | 0x80).
785 *
786 * Use of this option enables correct handling of user-generated SIGTRAPs,
787 * and SIGTRAPs generated by special instructions such as int3 on x86:
788 * _start: .globl _start
789 * int3
790 * movl $42, %ebx
791 * movl $1, %eax
792 * int $0x80
793 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
794 */
795static void
796test_ptrace_setoptions_for_all(void)
797{
798 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
799 int pid;
800 int it_worked = 0;
801
802 pid = fork();
803 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200804 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200805
806 if (pid == 0) {
807 pid = getpid();
808 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200809 /* Note: exits with exitcode 1 */
810 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200811 kill(pid, SIGSTOP);
812 _exit(0); /* parent should see entry into this syscall */
813 }
814
815 while (1) {
816 int status, tracee_pid;
817
818 errno = 0;
819 tracee_pid = wait(&status);
820 if (tracee_pid <= 0) {
821 if (errno == EINTR)
822 continue;
823 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200824 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200825 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200826 if (WIFEXITED(status)) {
827 if (WEXITSTATUS(status) == 0)
828 break;
829 /* PTRACE_TRACEME failed in child. This is fatal. */
830 exit(1);
831 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200832 if (!WIFSTOPPED(status)) {
833 kill(pid, SIGKILL);
834 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
835 }
836 if (WSTOPSIG(status) == SIGSTOP) {
837 /*
838 * We don't check "options aren't accepted" error.
839 * If it happens, we'll never get (SIGTRAP | 0x80),
840 * and thus will decide to not use the option.
841 * IOW: the outcome of the test will be correct.
842 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200843 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
844 if (errno != EINVAL)
845 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200846 }
847 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
848 it_worked = 1;
849 }
850 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
851 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200852 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200853 }
854 }
855
856 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200857 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200858 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200859 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200860 fprintf(stderr, "ptrace_setoptions = %#x\n",
861 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200862 return;
863 }
864
865 fprintf(stderr,
866 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
867}
Wang Chaob13c0de2010-11-12 17:25:19 +0800868#endif
869
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000871main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000872{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000873 struct tcb *tcp;
874 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000875 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000876 struct sigaction sa;
877
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000878 progname = argv[0] ? argv[0] : "strace";
879
Denys Vlasenko75422762011-05-27 14:36:01 +0200880 strace_tracer_pid = getpid();
881
Roland McGrathee9d4352002-12-18 04:16:10 +0000882 /* Allocate the initial tcbtab. */
883 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200884 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200885 if (tcbtab == NULL)
886 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200887 tcp = calloc(tcbtabsize, sizeof(*tcp));
888 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200889 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200890 for (c = 0; c < tcbtabsize; c++)
891 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000892
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 outf = stderr;
894 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000895 set_sortby(DEFAULT_SORTBY);
896 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897 qualify("trace=all");
898 qualify("abbrev=all");
899 qualify("verbose=all");
900 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000902 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000903#ifndef USE_PROCFS
904 "D"
905#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000906 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000907 switch (c) {
908 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000909 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200910 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000911 }
912 cflag = CFLAG_ONLY_STATS;
913 break;
914 case 'C':
915 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200916 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000917 }
918 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919 break;
920 case 'd':
921 debug++;
922 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000923#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000924 case 'D':
925 daemonized_tracer = 1;
926 break;
927#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000928 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000929 optF = 1;
930 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 case 'f':
932 followfork++;
933 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934 case 'h':
935 usage(stdout, 0);
936 break;
937 case 'i':
938 iflag++;
939 break;
940 case 'q':
941 qflag++;
942 break;
943 case 'r':
944 rflag++;
945 tflag++;
946 break;
947 case 't':
948 tflag++;
949 break;
950 case 'T':
951 dtime++;
952 break;
953 case 'x':
954 xflag++;
955 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000956 case 'y':
957 show_fd_path = 1;
958 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959 case 'v':
960 qualify("abbrev=none");
961 break;
962 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000963 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964 exit(0);
965 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000966 case 'z':
967 not_failing_only = 1;
968 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 case 'a':
970 acolumn = atoi(optarg);
971 break;
972 case 'e':
973 qualify(optarg);
974 break;
975 case 'o':
976 outfname = strdup(optarg);
977 break;
978 case 'O':
979 set_overhead(atoi(optarg));
980 break;
981 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000982 if ((pid = atoi(optarg)) <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200983 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 break;
985 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200986 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200987 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 break;
989 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000990 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 tcp->flags |= TCB_ATTACHED;
992 pflag_seen++;
993 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000994 case 'P':
995 tracing_paths = 1;
996 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200997 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +0000998 }
999 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 case 's':
1001 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001002 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001003 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001004 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 break;
1006 case 'S':
1007 set_sortby(optarg);
1008 break;
1009 case 'u':
1010 username = strdup(optarg);
1011 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001012 case 'E':
1013 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001014 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001015 }
1016 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017 default:
1018 usage(stderr, 1);
1019 break;
1020 }
1021 }
1022
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001023 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001024 usage(stderr, 1);
1025
Wang Chaod322a4b2010-08-05 14:30:11 +08001026 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001027 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001028 }
1029
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001030 if (!followfork)
1031 followfork = optF;
1032
Roland McGrathcb9def62006-04-25 07:48:03 +00001033 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001034 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001035 }
1036
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 /* See if they want to run as another user. */
1038 if (username != NULL) {
1039 struct passwd *pent;
1040
1041 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001042 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 }
1044 if ((pent = getpwnam(username)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001045 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 }
1047 run_uid = pent->pw_uid;
1048 run_gid = pent->pw_gid;
1049 }
1050 else {
1051 run_uid = getuid();
1052 run_gid = getgid();
1053 }
1054
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001055#ifdef LINUX
1056 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001057 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001058 fprintf(stderr,
1059 "Test for options supported by PTRACE_SETOPTIONS "
1060 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001061 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001062 }
1063 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001064 fprintf(stderr, "ptrace_setoptions = %#x\n",
1065 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001066 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001067 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001068#endif
1069
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 /* Check if they want to redirect the output. */
1071 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001072 /* See if they want to pipe the output. */
1073 if (outfname[0] == '|' || outfname[0] == '!') {
1074 /*
1075 * We can't do the <outfname>.PID funny business
1076 * when using popen, so prohibit it.
1077 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001078 if (followfork > 1)
1079 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1080 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001081 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001082 else if (followfork <= 1)
1083 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 }
1085
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001086 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1087 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001089 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001090 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001093 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001094
Roland McGrath54cc1c82007-11-03 23:34:11 +00001095 /* Valid states here:
1096 optind < argc pflag_seen outfname interactive
1097 1 0 0 1
1098 0 1 0 1
1099 1 0 1 0
1100 0 1 1 1
1101 */
1102
1103 /* STARTUP_CHILD must be called before the signal handlers get
1104 installed below as they are inherited into the spawned process.
1105 Also we do not need to be protected by them as during interruption
1106 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1107 if (!pflag_seen)
1108 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 sigemptyset(&empty_set);
1111 sigemptyset(&blocked_set);
1112 sa.sa_handler = SIG_IGN;
1113 sigemptyset(&sa.sa_mask);
1114 sa.sa_flags = 0;
1115 sigaction(SIGTTOU, &sa, NULL);
1116 sigaction(SIGTTIN, &sa, NULL);
1117 if (interactive) {
1118 sigaddset(&blocked_set, SIGHUP);
1119 sigaddset(&blocked_set, SIGINT);
1120 sigaddset(&blocked_set, SIGQUIT);
1121 sigaddset(&blocked_set, SIGPIPE);
1122 sigaddset(&blocked_set, SIGTERM);
1123 sa.sa_handler = interrupt;
1124#ifdef SUNOS4
1125 /* POSIX signals on sunos4.1 are a little broken. */
1126 sa.sa_flags = SA_INTERRUPT;
1127#endif /* SUNOS4 */
1128 }
1129 sigaction(SIGHUP, &sa, NULL);
1130 sigaction(SIGINT, &sa, NULL);
1131 sigaction(SIGQUIT, &sa, NULL);
1132 sigaction(SIGPIPE, &sa, NULL);
1133 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001134#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 sa.sa_handler = reaper;
1136 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001137#else
1138 /* Make sure SIGCHLD has the default action so that waitpid
1139 definitely works without losing track of children. The user
1140 should not have given us a bogus state to inherit, but he might
1141 have. Arguably we should detect SIG_IGN here and pass it on
1142 to children, but probably noone really needs that. */
1143 sa.sa_handler = SIG_DFL;
1144 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001145#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001147 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001148 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001149
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 if (trace() < 0)
1151 exit(1);
1152 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001153 fflush(NULL);
1154 if (exit_code > 0xff) {
1155 /* Child was killed by a signal, mimic that. */
1156 exit_code &= 0xff;
1157 signal(exit_code, SIG_DFL);
1158 raise(exit_code);
1159 /* Paranoia - what if this signal is not fatal?
1160 Exit with 128 + signo then. */
1161 exit_code += 128;
1162 }
1163 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164}
1165
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001166static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001167expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001168{
1169 /* Allocate some more TCBs and expand the table.
1170 We don't want to relocate the TCBs because our
1171 callers have pointers and it would be a pain.
1172 So tcbtab is a table of pointers. Since we never
1173 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001174 int i = tcbtabsize;
1175 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1176 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1177 if (newtab == NULL || newtcbs == NULL)
1178 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001179 tcbtabsize *= 2;
1180 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001181 while (i < tcbtabsize)
1182 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001183}
1184
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001186alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187{
1188 int i;
1189 struct tcb *tcp;
1190
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001191 if (nprocs == tcbtabsize)
1192 expand_tcbtab();
1193
Roland McGrathee9d4352002-12-18 04:16:10 +00001194 for (i = 0; i < tcbtabsize; i++) {
1195 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001197 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 tcp->flags = TCB_INUSE | TCB_STARTUP;
1200 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 tcp->pfd = -1;
1202 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001203 if (command_options_parsed)
1204 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 return tcp;
1206 }
1207 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001208 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209}
1210
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001211#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001213proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214{
1215 char proc[32];
1216 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001217#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001218 int i;
1219 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220 sigset_t signals;
1221 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001222#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223#ifndef HAVE_POLLABLE_PROCFS
1224 static int last_pfd;
1225#endif
1226
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001227#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001228 /* Open the process pseudo-files in /proc. */
1229 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1230 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 perror("strace: open(\"/proc/...\", ...)");
1232 return -1;
1233 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001234 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001235 sprintf(proc, "/proc/%d/status", tcp->pid);
1236 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1237 perror("strace: open(\"/proc/...\", ...)");
1238 return -1;
1239 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001240 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001241 sprintf(proc, "/proc/%d/as", tcp->pid);
1242 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1243 perror("strace: open(\"/proc/...\", ...)");
1244 return -1;
1245 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001246 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001247#else
1248 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001249#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001250 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001251 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001252#else /* FREEBSD */
1253 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001254 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001255#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001256 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001257 perror("strace: open(\"/proc/...\", ...)");
1258 return -1;
1259 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001260 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001261#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001262#ifdef FREEBSD
1263 sprintf(proc, "/proc/%d/regs", tcp->pid);
1264 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1265 perror("strace: open(\"/proc/.../regs\", ...)");
1266 return -1;
1267 }
1268 if (cflag) {
1269 sprintf(proc, "/proc/%d/status", tcp->pid);
1270 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1271 perror("strace: open(\"/proc/.../status\", ...)");
1272 return -1;
1273 }
1274 } else
1275 tcp->pfd_status = -1;
1276#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001277 rebuild_pollv();
1278 if (!attaching) {
1279 /*
1280 * Wait for the child to pause. Because of a race
1281 * condition we have to poll for the event.
1282 */
1283 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001284 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001285 perror("strace: PIOCSTATUS");
1286 return -1;
1287 }
1288 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001289 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001290 }
1291 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001292#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001293 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001294 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001295 perror("strace: PIOCSTOP");
1296 return -1;
1297 }
Roland McGrath553a6092002-12-16 20:40:39 +00001298#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299#ifdef PIOCSET
1300 /* Set Run-on-Last-Close. */
1301 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001302 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001303 perror("PIOCSET PR_RLC");
1304 return -1;
1305 }
1306 /* Set or Reset Inherit-on-Fork. */
1307 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001308 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309 perror("PIOC{SET,RESET} PR_FORK");
1310 return -1;
1311 }
1312#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001313#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1315 perror("PIOCSRLC");
1316 return -1;
1317 }
1318 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1319 perror("PIOC{S,R}FORK");
1320 return -1;
1321 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001322#else /* FREEBSD */
1323 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1324 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1325 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001326 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001327 }
1328 arg &= ~PF_LINGER;
1329 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001330 perror("PIOCSFL");
1331 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001332 }
1333#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001335#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001336 /* Enable all syscall entries we care about. */
1337 premptyset(&syscalls);
1338 for (i = 1; i < MAX_QUALS; ++i) {
1339 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001340 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001341 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001342 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001343 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001344 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001345#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001346 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001347#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001348#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001349 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001350#endif
1351#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001352 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001353#endif
1354#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001355 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001356#endif
1357 }
1358 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359 perror("PIOCSENTRY");
1360 return -1;
1361 }
John Hughes19e49982001-10-19 08:59:12 +00001362 /* Enable the syscall exits. */
1363 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364 perror("PIOSEXIT");
1365 return -1;
1366 }
John Hughes19e49982001-10-19 08:59:12 +00001367 /* Enable signals we care about. */
1368 premptyset(&signals);
1369 for (i = 1; i < MAX_QUALS; ++i) {
1370 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001371 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001372 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001373 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374 perror("PIOCSTRACE");
1375 return -1;
1376 }
John Hughes19e49982001-10-19 08:59:12 +00001377 /* Enable faults we care about */
1378 premptyset(&faults);
1379 for (i = 1; i < MAX_QUALS; ++i) {
1380 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001381 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001382 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 perror("PIOCSFAULT");
1385 return -1;
1386 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001387#else /* FREEBSD */
1388 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001389 arg = S_SIG | S_SCE | S_SCX;
1390 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001391 perror("PIOCBIS");
1392 return -1;
1393 }
1394#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395 if (!attaching) {
1396#ifdef MIPS
1397 /*
1398 * The SGI PRSABORT doesn't work for pause() so
1399 * we send it a caught signal to wake it up.
1400 */
1401 kill(tcp->pid, SIGINT);
1402#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001403#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001405 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001406 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001407 perror("PIOCRUN");
1408 return -1;
1409 }
Roland McGrath553a6092002-12-16 20:40:39 +00001410#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001411#endif /* !MIPS*/
1412#ifdef FREEBSD
1413 /* wake up the child if it received the SIGSTOP */
1414 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001415#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416 for (;;) {
1417 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001418 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001419 perror("PIOCWSTOP");
1420 return -1;
1421 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001422 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001423 tcp->flags &= ~TCB_INSYSCALL;
1424 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001425 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426 break;
1427 }
1428 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001429#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001430 arg = 0;
1431 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001432#else /* FREEBSD */
1433 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001434#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 perror("PIOCRUN");
1436 return -1;
1437 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001438#ifdef FREEBSD
1439 /* handle the case where we "opened" the child before
1440 it did the kill -STOP */
1441 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1442 tcp->status.PR_WHAT == SIGSTOP)
1443 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001444#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001446#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001448#else /* FREEBSD */
1449 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001450 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001451 /* We are attaching to an already running process.
1452 * Try to figure out the state of the process in syscalls,
1453 * to handle the first event well.
1454 * This is done by having a look at the "wchan" property of the
1455 * process, which tells where it is stopped (if it is). */
1456 FILE * status;
1457 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001458
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001459 sprintf(proc, "/proc/%d/status", tcp->pid);
1460 status = fopen(proc, "r");
1461 if (status &&
1462 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1463 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1464 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1465 strcmp(wchan, "stopevent")) {
1466 /* The process is asleep in the middle of a syscall.
1467 Fake the syscall entry event */
1468 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1469 tcp->status.PR_WHY = PR_SYSENTRY;
1470 trace_syscall(tcp);
1471 }
1472 if (status)
1473 fclose(status);
1474 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001475 }
1476#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477#ifndef HAVE_POLLABLE_PROCFS
1478 if (proc_poll_pipe[0] != -1)
1479 proc_poller(tcp->pfd);
1480 else if (nprocs > 1) {
1481 proc_poll_open();
1482 proc_poller(last_pfd);
1483 proc_poller(tcp->pfd);
1484 }
1485 last_pfd = tcp->pfd;
1486#endif /* !HAVE_POLLABLE_PROCFS */
1487 return 0;
1488}
1489
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001490#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001492struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001493pid2tcb(int pid)
1494{
1495 int i;
1496
1497 if (pid <= 0)
1498 return NULL;
1499
1500 for (i = 0; i < tcbtabsize; i++) {
1501 struct tcb *tcp = tcbtab[i];
1502 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1503 return tcp;
1504 }
1505
1506 return NULL;
1507}
1508
1509#ifdef USE_PROCFS
1510
1511static struct tcb *
1512first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513{
1514 int i;
1515 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001516 for (i = 0; i < tcbtabsize; i++) {
1517 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518 if (tcp->flags & TCB_INUSE)
1519 return tcp;
1520 }
1521 return NULL;
1522}
1523
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001525pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526{
1527 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528
Roland McGrathca16be82003-01-10 19:55:28 +00001529 for (i = 0; i < tcbtabsize; i++) {
1530 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531 if (tcp->pfd != pfd)
1532 continue;
1533 if (tcp->flags & TCB_INUSE)
1534 return tcp;
1535 }
1536 return NULL;
1537}
1538
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001539#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540
1541void
Denys Vlasenko12014262011-05-30 14:00:14 +02001542droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543{
1544 if (tcp->pid == 0)
1545 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001546#ifdef TCB_CLONE_THREAD
1547 if (tcp->nclone_threads > 0) {
1548 /* There are other threads left in this process, but this
1549 is the one whose PID represents the whole process.
1550 We need to keep this record around as a zombie until
1551 all the threads die. */
1552 tcp->flags |= TCB_EXITING;
1553 return;
1554 }
1555#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556 nprocs--;
1557 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001558
Roland McGrathe29341c2003-01-10 20:14:20 +00001559 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001560#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001561 if (tcp->flags & TCB_CLONE_THREAD)
1562 tcp->parent->nclone_threads--;
1563#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001564#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001565 /* Update fields like NCLONE_DETACHED, only
1566 for zombie group leader that has already reported
1567 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001568 function. The same condition as at the top of DETACH. */
1569 if ((tcp->flags & TCB_CLONE_THREAD) &&
1570 tcp->parent->nclone_threads == 0 &&
1571 (tcp->parent->flags & TCB_EXITING))
1572 droptcb(tcp->parent);
1573#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001574 tcp->parent = NULL;
1575 }
1576
1577 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578 if (tcp->pfd != -1) {
1579 close(tcp->pfd);
1580 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001581#ifdef FREEBSD
1582 if (tcp->pfd_reg != -1) {
1583 close(tcp->pfd_reg);
1584 tcp->pfd_reg = -1;
1585 }
1586 if (tcp->pfd_status != -1) {
1587 close(tcp->pfd_status);
1588 tcp->pfd_status = -1;
1589 }
Roland McGrath553a6092002-12-16 20:40:39 +00001590#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001591#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001592 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593#endif
1594 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001595
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001596 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001598
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599 tcp->outf = 0;
1600}
1601
Roland McGrath0a463882007-07-05 18:43:16 +00001602/* detach traced process; continue with sig
1603 Never call DETACH twice on the same process as both unattached and
1604 attached-unstopped processes give the same ESRCH. For unattached process we
1605 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606
1607static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001608detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609{
1610 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001611#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001612 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001613 struct tcb *zombie = NULL;
1614
1615 /* If the group leader is lingering only because of this other
1616 thread now dying, then detach the leader as well. */
1617 if ((tcp->flags & TCB_CLONE_THREAD) &&
1618 tcp->parent->nclone_threads == 1 &&
1619 (tcp->parent->flags & TCB_EXITING))
1620 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001621#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622
1623 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001624 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625
1626#ifdef LINUX
1627 /*
1628 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001629 * before detaching. Arghh. We go through hoops
1630 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001632#if defined(SPARC)
1633#undef PTRACE_DETACH
1634#define PTRACE_DETACH PTRACE_SUNDETACH
1635#endif
Roland McGrath02203312007-06-11 22:06:31 +00001636 /*
1637 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1638 * expected SIGSTOP. We must catch exactly one as otherwise the
1639 * detached process would be left stopped (process state T).
1640 */
1641 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1643 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001644 }
1645 else if (errno != ESRCH) {
1646 /* Shouldn't happen. */
1647 perror("detach: ptrace(PTRACE_DETACH, ...)");
1648 }
Roland McGrath134813a2007-06-02 00:07:33 +00001649 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1650 : tcp->pid),
1651 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001652 if (errno != ESRCH)
1653 perror("detach: checking sanity");
1654 }
Roland McGrath02203312007-06-11 22:06:31 +00001655 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1656 ? tcp->parent->pid : tcp->pid),
1657 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001658 if (errno != ESRCH)
1659 perror("detach: stopping child");
1660 }
Roland McGrath02203312007-06-11 22:06:31 +00001661 else
1662 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001663 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001665#ifdef __WALL
1666 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1667 if (errno == ECHILD) /* Already gone. */
1668 break;
1669 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001670 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001671 break;
1672 }
1673#endif /* __WALL */
1674 /* No __WALL here. */
1675 if (waitpid(tcp->pid, &status, 0) < 0) {
1676 if (errno != ECHILD) {
1677 perror("detach: waiting");
1678 break;
1679 }
1680#ifdef __WCLONE
1681 /* If no processes, try clones. */
1682 if (wait4(tcp->pid, &status, __WCLONE,
1683 NULL) < 0) {
1684 if (errno != ECHILD)
1685 perror("detach: waiting");
1686 break;
1687 }
1688#endif /* __WCLONE */
1689 }
1690#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001691 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001692#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 if (!WIFSTOPPED(status)) {
1694 /* Au revoir, mon ami. */
1695 break;
1696 }
1697 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001698 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699 break;
1700 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001701 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001702 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001703 : WSTOPSIG(status));
1704 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001707 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001708#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709
1710#if defined(SUNOS4)
1711 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1712 if (sig && kill(tcp->pid, sig) < 0)
1713 perror("detach: kill");
1714 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001715 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716#endif /* SUNOS4 */
1717
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 if (!qflag)
1719 fprintf(stderr, "Process %u detached\n", tcp->pid);
1720
1721 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001722
1723#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001724 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001725 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001726 droptcb(zombie);
1727 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001728#endif
1729
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 return error;
1731}
1732
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001733#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001735static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736{
1737 int pid;
1738 int status;
1739
1740 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001741 }
1742}
1743
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001744#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745
1746static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001747cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748{
1749 int i;
1750 struct tcb *tcp;
1751
Roland McGrathee9d4352002-12-18 04:16:10 +00001752 for (i = 0; i < tcbtabsize; i++) {
1753 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754 if (!(tcp->flags & TCB_INUSE))
1755 continue;
1756 if (debug)
1757 fprintf(stderr,
1758 "cleanup: looking at pid %u\n", tcp->pid);
1759 if (tcp_last &&
1760 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001761 tprintf(" <unfinished ...>");
1762 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 }
1764 if (tcp->flags & TCB_ATTACHED)
1765 detach(tcp, 0);
1766 else {
1767 kill(tcp->pid, SIGCONT);
1768 kill(tcp->pid, SIGTERM);
1769 }
1770 }
1771 if (cflag)
1772 call_summary(outf);
1773}
1774
1775static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001776interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777{
1778 interrupted = 1;
1779}
1780
1781#ifndef HAVE_STRERROR
1782
Roland McGrath6d2b3492002-12-30 00:51:30 +00001783#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001784extern int sys_nerr;
1785extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001786#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787
1788const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001789strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790{
1791 static char buf[64];
1792
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001793 if (err_no < 1 || err_no >= sys_nerr) {
1794 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 return buf;
1796 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001797 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798}
1799
1800#endif /* HAVE_STERRROR */
1801
1802#ifndef HAVE_STRSIGNAL
1803
Roland McGrath8f474e02003-01-14 07:53:33 +00001804#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001805extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001807#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1808extern char *_sys_siglist[];
1809#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810
1811const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001812strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813{
1814 static char buf[64];
1815
1816 if (sig < 1 || sig >= NSIG) {
1817 sprintf(buf, "Unknown signal %d", sig);
1818 return buf;
1819 }
1820#ifdef HAVE__SYS_SIGLIST
1821 return _sys_siglist[sig];
1822#else
1823 return sys_siglist[sig];
1824#endif
1825}
1826
1827#endif /* HAVE_STRSIGNAL */
1828
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001829#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830
1831static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001832rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833{
1834 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001835
Roland McGrathee9d4352002-12-18 04:16:10 +00001836 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001837 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001838 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001839 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001840 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001841 }
1842
Roland McGrathca16be82003-01-10 19:55:28 +00001843 for (i = j = 0; i < tcbtabsize; i++) {
1844 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845 if (!(tcp->flags & TCB_INUSE))
1846 continue;
1847 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001848 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849 j++;
1850 }
1851 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001852 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853 }
1854}
1855
1856#ifndef HAVE_POLLABLE_PROCFS
1857
1858static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001859proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861 int i;
1862
1863 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001864 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 }
1866 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001867 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868 }
1869}
1870
1871static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001872proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873{
1874 int i;
1875 int n;
1876 struct proc_pollfd pollinfo;
1877
1878 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1879 return n;
1880 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001881 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882 }
1883 for (i = 0; i < nprocs; i++) {
1884 if (pollv[i].fd == pollinfo.fd)
1885 pollv[i].revents = pollinfo.revents;
1886 else
1887 pollv[i].revents = 0;
1888 }
1889 poller_pid = pollinfo.pid;
1890 return 1;
1891}
1892
1893static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001894wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001895{
1896}
1897
1898static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001899proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001900{
1901 struct proc_pollfd pollinfo;
1902 struct sigaction sa;
1903 sigset_t blocked_set, empty_set;
1904 int i;
1905 int n;
1906 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001907#ifdef FREEBSD
1908 struct procfs_status pfs;
1909#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910
1911 switch (fork()) {
1912 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001913 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 case 0:
1915 break;
1916 default:
1917 return;
1918 }
1919
1920 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1921 sa.sa_flags = 0;
1922 sigemptyset(&sa.sa_mask);
1923 sigaction(SIGHUP, &sa, NULL);
1924 sigaction(SIGINT, &sa, NULL);
1925 sigaction(SIGQUIT, &sa, NULL);
1926 sigaction(SIGPIPE, &sa, NULL);
1927 sigaction(SIGTERM, &sa, NULL);
1928 sa.sa_handler = wakeup_handler;
1929 sigaction(SIGUSR1, &sa, NULL);
1930 sigemptyset(&blocked_set);
1931 sigaddset(&blocked_set, SIGUSR1);
1932 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1933 sigemptyset(&empty_set);
1934
1935 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001936 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001937 }
1938 n = rl.rlim_cur;
1939 for (i = 0; i < n; i++) {
1940 if (i != pfd && i != proc_poll_pipe[1])
1941 close(i);
1942 }
1943
1944 pollinfo.fd = pfd;
1945 pollinfo.pid = getpid();
1946 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001947#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001948 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1949#else
1950 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1951#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001952 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 switch (errno) {
1954 case EINTR:
1955 continue;
1956 case EBADF:
1957 pollinfo.revents = POLLERR;
1958 break;
1959 case ENOENT:
1960 pollinfo.revents = POLLHUP;
1961 break;
1962 default:
1963 perror("proc_poller: PIOCWSTOP");
1964 }
1965 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1966 _exit(0);
1967 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001968 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1970 sigsuspend(&empty_set);
1971 }
1972}
1973
1974#endif /* !HAVE_POLLABLE_PROCFS */
1975
1976static int
1977choose_pfd()
1978{
1979 int i, j;
1980 struct tcb *tcp;
1981
1982 static int last;
1983
1984 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001985 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 /*
1987 * The previous process is ready to run again. We'll
1988 * let it do so if it is currently in a syscall. This
1989 * heuristic improves the readability of the trace.
1990 */
1991 tcp = pfd2tcb(pollv[last].fd);
1992 if (tcp && (tcp->flags & TCB_INSYSCALL))
1993 return pollv[last].fd;
1994 }
1995
1996 for (i = 0; i < nprocs; i++) {
1997 /* Let competing children run round robin. */
1998 j = (i + last + 1) % nprocs;
1999 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2000 tcp = pfd2tcb(pollv[j].fd);
2001 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002002 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003 }
2004 droptcb(tcp);
2005 return -1;
2006 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002007 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002008 last = j;
2009 return pollv[j].fd;
2010 }
2011 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002012 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002013}
2014
2015static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002016trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002018#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002019 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002020#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 struct tcb *tcp;
2022 int pfd;
2023 int what;
2024 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002025 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026
2027 for (;;) {
2028 if (interactive)
2029 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2030
2031 if (nprocs == 0)
2032 break;
2033
2034 switch (nprocs) {
2035 case 1:
2036#ifndef HAVE_POLLABLE_PROCFS
2037 if (proc_poll_pipe[0] == -1) {
2038#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002039 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 if (!tcp)
2041 continue;
2042 pfd = tcp->pfd;
2043 if (pfd == -1)
2044 continue;
2045 break;
2046#ifndef HAVE_POLLABLE_PROCFS
2047 }
2048 /* fall through ... */
2049#endif /* !HAVE_POLLABLE_PROCFS */
2050 default:
2051#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002052#ifdef POLL_HACK
2053 /* On some systems (e.g. UnixWare) we get too much ugly
2054 "unfinished..." stuff when multiple proceses are in
2055 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002056
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002057 if (in_syscall) {
2058 struct pollfd pv;
2059 tcp = in_syscall;
2060 in_syscall = NULL;
2061 pv.fd = tcp->pfd;
2062 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002063 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002064 if (interrupted)
2065 return 0;
2066 continue;
2067 }
2068 else if (what == 1 && pv.revents & POLLWANT) {
2069 goto FOUND;
2070 }
2071 }
2072#endif
2073
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002074 if (poll(pollv, nprocs, INFTIM) < 0) {
2075 if (interrupted)
2076 return 0;
2077 continue;
2078 }
2079#else /* !HAVE_POLLABLE_PROCFS */
2080 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2081 if (interrupted)
2082 return 0;
2083 continue;
2084 }
2085#endif /* !HAVE_POLLABLE_PROCFS */
2086 pfd = choose_pfd();
2087 if (pfd == -1)
2088 continue;
2089 break;
2090 }
2091
2092 /* Look up `pfd' in our table. */
2093 if ((tcp = pfd2tcb(pfd)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002094 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 }
John Hughesb6643082002-05-23 11:02:22 +00002096#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002097 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002098#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 /* Get the status of the process. */
2100 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002101#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002102 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002103#else /* FREEBSD */
2104 /* Thanks to some scheduling mystery, the first poller
2105 sometimes waits for the already processed end of fork
2106 event. Doing a non blocking poll here solves the problem. */
2107 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002108 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002109 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002110 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002111#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112 ioctl_errno = errno;
2113#ifndef HAVE_POLLABLE_PROCFS
2114 if (proc_poll_pipe[0] != -1) {
2115 if (ioctl_result < 0)
2116 kill(poller_pid, SIGKILL);
2117 else
2118 kill(poller_pid, SIGUSR1);
2119 }
2120#endif /* !HAVE_POLLABLE_PROCFS */
2121 }
2122 if (interrupted)
2123 return 0;
2124
2125 if (interactive)
2126 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2127
2128 if (ioctl_result < 0) {
2129 /* Find out what happened if it failed. */
2130 switch (ioctl_errno) {
2131 case EINTR:
2132 case EBADF:
2133 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002134#ifdef FREEBSD
2135 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002136#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137 case ENOENT:
2138 droptcb(tcp);
2139 continue;
2140 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002141 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 }
2143 }
2144
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002145#ifdef FREEBSD
2146 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2147 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002148 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002149 continue;
2150 }
Roland McGrath553a6092002-12-16 20:40:39 +00002151#endif
2152
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 /* clear the just started flag */
2154 tcp->flags &= ~TCB_STARTUP;
2155
2156 /* set current output file */
2157 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002158 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002159
2160 if (cflag) {
2161 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002162#ifdef FREEBSD
2163 char buf[1024];
2164 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002165
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002166 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2167 buf[len] = '\0';
2168 sscanf(buf,
2169 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2170 &stime.tv_sec, &stime.tv_usec);
2171 } else
2172 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002173#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002174 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2175 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002176#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2178 tcp->stime = stime;
2179 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002180 what = tcp->status.PR_WHAT;
2181 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002182#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002183 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002184 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2185 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002187 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188 }
2189 }
2190 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002191#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002193#ifdef POLL_HACK
2194 in_syscall = tcp;
2195#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 case PR_SYSEXIT:
2197 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002198 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199 }
2200 break;
2201 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002202 if (cflag != CFLAG_ONLY_STATS
2203 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204 printleader(tcp);
2205 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002206 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002207 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002208#ifdef PR_INFO
2209 if (tcp->status.PR_INFO.si_signo == what) {
2210 printleader(tcp);
2211 tprintf(" siginfo=");
2212 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002213 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002214 }
2215#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002216 }
2217 break;
2218 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002219 if (cflag != CFLAGS_ONLY_STATS
2220 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221 printleader(tcp);
2222 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002223 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224 }
2225 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002226#ifdef FREEBSD
2227 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002228 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002229#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002230 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002231 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002232 break;
2233 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002234 /* Remember current print column before continuing. */
2235 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002236 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002237#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002238 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002239#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002240 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002241#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002242 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002243 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244 }
2245 }
2246 return 0;
2247}
2248
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002249#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002250
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002251#ifdef TCB_GROUP_EXITING
2252/* Handle an exit detach or death signal that is taking all the
2253 related clone threads with it. This is called in three circumstances:
2254 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2255 SIG == 0 Continuing TCP will perform an exit_group syscall.
2256 SIG == other Continuing TCP with SIG will kill the process.
2257*/
2258static int
2259handle_group_exit(struct tcb *tcp, int sig)
2260{
2261 /* We need to locate our records of all the clone threads
2262 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002263 struct tcb *leader = NULL;
2264
2265 if (tcp->flags & TCB_CLONE_THREAD)
2266 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002267
2268 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002269 if (leader != NULL && leader != tcp
2270 && !(leader->flags & TCB_GROUP_EXITING)
2271 && !(tcp->flags & TCB_STARTUP)
2272 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002273 fprintf(stderr,
2274 "PANIC: handle_group_exit: %d leader %d\n",
2275 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002276 }
2277 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002278 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002279 }
2280 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002281 /* Mark that we are taking the process down. */
2282 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002283 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002284 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002285 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002286 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002287 } else {
2288 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2289 cleanup();
2290 return -1;
2291 }
2292 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002293 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002294 if (leader != tcp)
2295 droptcb(tcp);
2296 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002297 /* The leader will report to us as parent now,
2298 and then we'll get to the SIG==-1 case. */
2299 return 0;
2300 }
2301 }
2302
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002303 return 0;
2304}
2305#endif
2306
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002307#ifdef LINUX
2308static int
2309handle_ptrace_event(int status, struct tcb *tcp)
2310{
2311 if (status >> 16 == PTRACE_EVENT_VFORK ||
2312 status >> 16 == PTRACE_EVENT_CLONE ||
2313 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002314 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002315
2316 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2317 if (errno != ESRCH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002318 error_msg_and_die("Cannot get new child's pid");
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002319 }
2320 return -1;
2321 }
2322 return handle_new_child(tcp, childpid, 0);
2323 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002324 if (status >> 16 == PTRACE_EVENT_EXEC) {
2325 if (debug)
2326 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2327 return 0;
2328 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002329 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2330 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002331 return 1;
2332}
2333#endif
2334
Roland McGratheb9e2e82009-06-02 16:49:22 -07002335static int
2336trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337{
2338 int pid;
2339 int wait_errno;
2340 int status;
2341 struct tcb *tcp;
2342#ifdef LINUX
2343 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002344#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002345 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002346#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347#endif /* LINUX */
2348
Roland McGratheb9e2e82009-06-02 16:49:22 -07002349 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002350 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002351 return 0;
2352 if (interactive)
2353 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002354#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002355#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002356 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002357 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002358 /* this kernel does not support __WALL */
2359 wait4_options &= ~__WALL;
2360 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002361 pid = wait4(-1, &status, wait4_options,
2362 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002363 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002364 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002365 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002366 pid = wait4(-1, &status, __WCLONE,
2367 cflag ? &ru : NULL);
2368 if (pid == -1) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002369 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002370 }
2371 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002372#else
2373 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2374#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002375#endif /* LINUX */
2376#ifdef SUNOS4
2377 pid = wait(&status);
2378#endif /* SUNOS4 */
2379 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002380 if (interactive)
2381 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002382
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002383 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002384 switch (wait_errno) {
2385 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002387 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388 /*
2389 * We would like to verify this case
2390 * but sometimes a race in Solbourne's
2391 * version of SunOS sometimes reports
2392 * ECHILD before sending us SIGCHILD.
2393 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002394 return 0;
2395 default:
2396 errno = wait_errno;
2397 perror("strace: wait");
2398 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002399 }
2400 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002401 if (pid == popen_pid) {
2402 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002403 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002404 continue;
2405 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002406 if (debug)
2407 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2408
2409 /* Look up `pid' in our table. */
2410 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002411#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002412 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002413 /* This is needed to go with the CLONE_PTRACE
2414 changes in process.c/util.c: we might see
2415 the child's initial trap before we see the
2416 parent return from the clone syscall.
2417 Leave the child suspended until the parent
2418 returns from its system call. Only then
2419 will we have the association of parent and
2420 child so that we know how to do clearbpt
2421 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002422 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002423 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002424 if (!qflag)
2425 fprintf(stderr, "\
2426Process %d attached (waiting for parent)\n",
2427 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002428 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002429 else
2430 /* This can happen if a clone call used
2431 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002432#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002433 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002434 if (WIFSTOPPED(status))
2435 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002436 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002437 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002438 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002439 /* set current output file */
2440 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002441 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002442 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002443#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2445 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002446#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002448
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449 if (tcp->flags & TCB_SUSPENDED) {
2450 /*
2451 * Apparently, doing any ptrace() call on a stopped
2452 * process, provokes the kernel to report the process
2453 * status again on a subsequent wait(), even if the
2454 * process has not been actually restarted.
2455 * Since we have inspected the arguments of suspended
2456 * processes we end up here testing for this case.
2457 */
2458 continue;
2459 }
2460 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002461 if (pid == strace_child)
2462 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002463 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002464 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2465 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002466 tprintf("+++ killed by %s %s+++",
2467 signame(WTERMSIG(status)),
2468#ifdef WCOREDUMP
2469 WCOREDUMP(status) ? "(core dumped) " :
2470#endif
2471 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002472 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002473 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002474#ifdef TCB_GROUP_EXITING
2475 handle_group_exit(tcp, -1);
2476#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002477 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002478#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479 continue;
2480 }
2481 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002482 if (pid == strace_child)
2483 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002484 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002485 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2486 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002487#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002488 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002489 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002490#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002491 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002492 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002493 "PANIC: attached pid %u exited with %d\n",
2494 pid, WEXITSTATUS(status));
2495 }
Roland McGrath0a396902003-06-10 03:05:53 +00002496 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002497 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002498 tprintf(" <unfinished ... exit status %d>\n",
2499 WEXITSTATUS(status));
2500 tcp_last = NULL;
2501 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002502#ifdef TCB_GROUP_EXITING
2503 handle_group_exit(tcp, -1);
2504#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002505 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002506#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002507 continue;
2508 }
2509 if (!WIFSTOPPED(status)) {
2510 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2511 droptcb(tcp);
2512 continue;
2513 }
2514 if (debug)
2515 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002516 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002517
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002518 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002519 if (handle_ptrace_event(status, tcp) != 1)
2520 goto tracing;
2521 }
2522
Roland McGrath02203312007-06-11 22:06:31 +00002523 /*
2524 * Interestingly, the process may stop
2525 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002526 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002527 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002528 * A no-MMU vforked child won't send up a signal,
2529 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002530 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002531 if ((tcp->flags & TCB_STARTUP) &&
2532 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 /*
2534 * This flag is there to keep us in sync.
2535 * Next time this process stops it should
2536 * really be entering a system call.
2537 */
2538 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002540 /*
2541 * One example is a breakpoint inherited from
2542 * parent through fork ().
2543 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2545 droptcb(tcp);
2546 cleanup();
2547 return -1;
2548 }
2549 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002550#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002551 /* If options were not set for this tracee yet */
2552 if (tcp->parent == NULL) {
2553 if (ptrace_setoptions) {
2554 if (debug)
2555 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2556 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2557 if (errno != ESRCH) {
2558 /* Should never happen, really */
2559 perror_msg_and_die("PTRACE_SETOPTIONS");
2560 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002561 }
2562 }
2563 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002564#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002565 goto tracing;
2566 }
2567
Denys Vlasenko75422762011-05-27 14:36:01 +02002568 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002569 if (WSTOPSIG(status) == SIGSTOP &&
2570 (tcp->flags & TCB_SIGTRAPPED)) {
2571 /*
2572 * Trapped attempt to block SIGTRAP
2573 * Hope we are back in control now.
2574 */
2575 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002576 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 cleanup();
2578 return -1;
2579 }
2580 continue;
2581 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002582 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002583 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002584 siginfo_t si;
2585#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002586 long pc = 0;
2587 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002588
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002589 upeek(tcp, PT_CR_IPSR, &psr);
2590 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002591
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002592# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002593 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002594# define PC_FORMAT_STR " @ %lx"
2595# define PC_FORMAT_ARG pc
2596#else
2597# define PC_FORMAT_STR "%s"
2598# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002599#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002600 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002601 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2602 tprintf("--- ");
2603 printsiginfo(&si, verbose(tcp));
2604 tprintf(" (%s)" PC_FORMAT_STR " ---",
2605 strsignal(WSTOPSIG(status)),
2606 PC_FORMAT_ARG);
2607 } else
2608 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2609 strsignal(WSTOPSIG(status)),
2610 signame(WSTOPSIG(status)),
2611 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002612 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613 }
Roland McGrath05690952004-10-20 01:00:27 +00002614 if (((tcp->flags & TCB_ATTACHED) ||
2615 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002616 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002617#ifdef TCB_GROUP_EXITING
2618 handle_group_exit(tcp, WSTOPSIG(status));
2619#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002620 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002621#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002622 continue;
2623 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002624 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625 cleanup();
2626 return -1;
2627 }
2628 tcp->flags &= ~TCB_SUSPENDED;
2629 continue;
2630 }
Roland McGrath02203312007-06-11 22:06:31 +00002631 /* we handled the STATUS, we are permitted to interrupt now. */
2632 if (interrupted)
2633 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002634 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2635 /* ptrace() failed in trace_syscall() with ESRCH.
2636 * Likely a result of process disappearing mid-flight.
2637 * Observed case: exit_group() terminating
2638 * all processes in thread group. In this case, threads
2639 * "disappear" in an unpredictable moment without any
2640 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002641 */
2642 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002643 if (tcp_last) {
2644 /* Do we have dangling line "syscall(param, param"?
2645 * Finish the line then. We cannot
2646 */
2647 tcp_last->flags |= TCB_REPRINT;
2648 tprintf(" <unfinished ...>");
2649 printtrailer();
2650 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002651 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002652 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002653 ptrace(PTRACE_KILL,
2654 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002655 droptcb(tcp);
2656 }
2657 continue;
2658 }
2659 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002660#ifdef TCB_GROUP_EXITING
2661 if (tcp->flags & TCB_GROUP_EXITING) {
2662 if (handle_group_exit(tcp, 0) < 0)
2663 return -1;
2664 continue;
2665 }
2666#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002667 if (tcp->flags & TCB_ATTACHED)
2668 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002669 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670 cleanup();
2671 return -1;
2672 }
2673 continue;
2674 }
2675 if (tcp->flags & TCB_SUSPENDED) {
2676 if (!qflag)
2677 fprintf(stderr, "Process %u suspended\n", pid);
2678 continue;
2679 }
2680 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002681 /* Remember current print column before continuing. */
2682 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002683 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002684 cleanup();
2685 return -1;
2686 }
2687 }
2688 return 0;
2689}
2690
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002691#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002692
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002693#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694
2695void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002697{
2698 va_list args;
2699
Andreas Schwabe5355de2009-10-27 16:56:43 +01002700 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002701 if (outf) {
2702 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002703 if (n < 0) {
2704 if (outf != stderr)
2705 perror(outfname == NULL
2706 ? "<writing to pipe>" : outfname);
2707 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002708 curcol += n;
2709 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002710 va_end(args);
2711 return;
2712}
2713
2714void
Denys Vlasenko12014262011-05-30 14:00:14 +02002715printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002716{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002717 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002718 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002719 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002720 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002721 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002722 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002723 tprintf("= ? <unavailable>\n");
2724 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002725 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002726 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002727 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002728 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002729 }
2730 curcol = 0;
2731 if ((followfork == 1 || pflag_seen > 1) && outfname)
2732 tprintf("%-5d ", tcp->pid);
2733 else if (nprocs > 1 && !outfname)
2734 tprintf("[pid %5u] ", tcp->pid);
2735 if (tflag) {
2736 char str[sizeof("HH:MM:SS")];
2737 struct timeval tv, dtv;
2738 static struct timeval otv;
2739
2740 gettimeofday(&tv, NULL);
2741 if (rflag) {
2742 if (otv.tv_sec == 0)
2743 otv = tv;
2744 tv_sub(&dtv, &tv, &otv);
2745 tprintf("%6ld.%06ld ",
2746 (long) dtv.tv_sec, (long) dtv.tv_usec);
2747 otv = tv;
2748 }
2749 else if (tflag > 2) {
2750 tprintf("%ld.%06ld ",
2751 (long) tv.tv_sec, (long) tv.tv_usec);
2752 }
2753 else {
2754 time_t local = tv.tv_sec;
2755 strftime(str, sizeof(str), "%T", localtime(&local));
2756 if (tflag > 1)
2757 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2758 else
2759 tprintf("%s ", str);
2760 }
2761 }
2762 if (iflag)
2763 printcall(tcp);
2764}
2765
2766void
Denys Vlasenko12014262011-05-30 14:00:14 +02002767tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002768{
2769 if (curcol < col)
2770 tprintf("%*s", col - curcol, "");
2771}
2772
2773void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002774printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002775{
2776 tprintf("\n");
2777 tcp_last = NULL;
2778}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002779
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002780#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002781
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002782int
2783mp_ioctl(int fd, int cmd, void *arg, int size)
2784{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002785 struct iovec iov[2];
2786 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002787
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002788 iov[0].iov_base = &cmd;
2789 iov[0].iov_len = sizeof cmd;
2790 if (arg) {
2791 ++n;
2792 iov[1].iov_base = arg;
2793 iov[1].iov_len = size;
2794 }
Roland McGrath553a6092002-12-16 20:40:39 +00002795
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002796 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002797}
2798
2799#endif