blob: d6788d5de3904e69703773d72386a691df11d3ea [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);
Denys Vlasenko65d7c4d2011-06-23 21:46:37 +0200478 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD;
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++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001203 if (debug)
1204 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001205 if (command_options_parsed)
1206 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 return tcp;
1208 }
1209 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001210 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211}
1212
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001213#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001215proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216{
1217 char proc[32];
1218 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001219#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001220 int i;
1221 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 sigset_t signals;
1223 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001224#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225#ifndef HAVE_POLLABLE_PROCFS
1226 static int last_pfd;
1227#endif
1228
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001229#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001230 /* Open the process pseudo-files in /proc. */
1231 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1232 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 perror("strace: open(\"/proc/...\", ...)");
1234 return -1;
1235 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001236 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001237 sprintf(proc, "/proc/%d/status", tcp->pid);
1238 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1239 perror("strace: open(\"/proc/...\", ...)");
1240 return -1;
1241 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001242 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001243 sprintf(proc, "/proc/%d/as", tcp->pid);
1244 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1245 perror("strace: open(\"/proc/...\", ...)");
1246 return -1;
1247 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001248 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001249#else
1250 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001252 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001253 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001254#else /* FREEBSD */
1255 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001256 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001257#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001258 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001259 perror("strace: open(\"/proc/...\", ...)");
1260 return -1;
1261 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001262 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001263#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001264#ifdef FREEBSD
1265 sprintf(proc, "/proc/%d/regs", tcp->pid);
1266 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1267 perror("strace: open(\"/proc/.../regs\", ...)");
1268 return -1;
1269 }
1270 if (cflag) {
1271 sprintf(proc, "/proc/%d/status", tcp->pid);
1272 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1273 perror("strace: open(\"/proc/.../status\", ...)");
1274 return -1;
1275 }
1276 } else
1277 tcp->pfd_status = -1;
1278#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001279 rebuild_pollv();
1280 if (!attaching) {
1281 /*
1282 * Wait for the child to pause. Because of a race
1283 * condition we have to poll for the event.
1284 */
1285 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001286 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001287 perror("strace: PIOCSTATUS");
1288 return -1;
1289 }
1290 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001291 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001292 }
1293 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001294#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001295 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001296 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001297 perror("strace: PIOCSTOP");
1298 return -1;
1299 }
Roland McGrath553a6092002-12-16 20:40:39 +00001300#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001301#ifdef PIOCSET
1302 /* Set Run-on-Last-Close. */
1303 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001304 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305 perror("PIOCSET PR_RLC");
1306 return -1;
1307 }
1308 /* Set or Reset Inherit-on-Fork. */
1309 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001310 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311 perror("PIOC{SET,RESET} PR_FORK");
1312 return -1;
1313 }
1314#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001315#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1317 perror("PIOCSRLC");
1318 return -1;
1319 }
1320 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1321 perror("PIOC{S,R}FORK");
1322 return -1;
1323 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001324#else /* FREEBSD */
1325 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1326 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1327 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001328 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001329 }
1330 arg &= ~PF_LINGER;
1331 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001332 perror("PIOCSFL");
1333 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001334 }
1335#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001338 /* Enable all syscall entries we care about. */
1339 premptyset(&syscalls);
1340 for (i = 1; i < MAX_QUALS; ++i) {
1341 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001342 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001343 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001344 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001345 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001346 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001347#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001348 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001349#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001350#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001351 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001352#endif
1353#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001354 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001355#endif
1356#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001357 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001358#endif
1359 }
1360 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001361 perror("PIOCSENTRY");
1362 return -1;
1363 }
John Hughes19e49982001-10-19 08:59:12 +00001364 /* Enable the syscall exits. */
1365 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001366 perror("PIOSEXIT");
1367 return -1;
1368 }
John Hughes19e49982001-10-19 08:59:12 +00001369 /* Enable signals we care about. */
1370 premptyset(&signals);
1371 for (i = 1; i < MAX_QUALS; ++i) {
1372 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001373 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001374 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001375 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376 perror("PIOCSTRACE");
1377 return -1;
1378 }
John Hughes19e49982001-10-19 08:59:12 +00001379 /* Enable faults we care about */
1380 premptyset(&faults);
1381 for (i = 1; i < MAX_QUALS; ++i) {
1382 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001383 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001384 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001385 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 perror("PIOCSFAULT");
1387 return -1;
1388 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001389#else /* FREEBSD */
1390 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001391 arg = S_SIG | S_SCE | S_SCX;
1392 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001393 perror("PIOCBIS");
1394 return -1;
1395 }
1396#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001397 if (!attaching) {
1398#ifdef MIPS
1399 /*
1400 * The SGI PRSABORT doesn't work for pause() so
1401 * we send it a caught signal to wake it up.
1402 */
1403 kill(tcp->pid, SIGINT);
1404#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001405#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001407 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001408 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001409 perror("PIOCRUN");
1410 return -1;
1411 }
Roland McGrath553a6092002-12-16 20:40:39 +00001412#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001413#endif /* !MIPS*/
1414#ifdef FREEBSD
1415 /* wake up the child if it received the SIGSTOP */
1416 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001417#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418 for (;;) {
1419 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001420 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421 perror("PIOCWSTOP");
1422 return -1;
1423 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001424 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001425 tcp->flags &= ~TCB_INSYSCALL;
1426 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001427 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428 break;
1429 }
1430 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001431#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001432 arg = 0;
1433 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001434#else /* FREEBSD */
1435 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001436#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437 perror("PIOCRUN");
1438 return -1;
1439 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001440#ifdef FREEBSD
1441 /* handle the case where we "opened" the child before
1442 it did the kill -STOP */
1443 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1444 tcp->status.PR_WHAT == SIGSTOP)
1445 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001446#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001448#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001450#else /* FREEBSD */
1451 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001452 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001453 /* We are attaching to an already running process.
1454 * Try to figure out the state of the process in syscalls,
1455 * to handle the first event well.
1456 * This is done by having a look at the "wchan" property of the
1457 * process, which tells where it is stopped (if it is). */
1458 FILE * status;
1459 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001460
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001461 sprintf(proc, "/proc/%d/status", tcp->pid);
1462 status = fopen(proc, "r");
1463 if (status &&
1464 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1465 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1466 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1467 strcmp(wchan, "stopevent")) {
1468 /* The process is asleep in the middle of a syscall.
1469 Fake the syscall entry event */
1470 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1471 tcp->status.PR_WHY = PR_SYSENTRY;
1472 trace_syscall(tcp);
1473 }
1474 if (status)
1475 fclose(status);
1476 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001477 }
1478#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479#ifndef HAVE_POLLABLE_PROCFS
1480 if (proc_poll_pipe[0] != -1)
1481 proc_poller(tcp->pfd);
1482 else if (nprocs > 1) {
1483 proc_poll_open();
1484 proc_poller(last_pfd);
1485 proc_poller(tcp->pfd);
1486 }
1487 last_pfd = tcp->pfd;
1488#endif /* !HAVE_POLLABLE_PROCFS */
1489 return 0;
1490}
1491
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001492#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001493
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001494struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001495pid2tcb(int pid)
1496{
1497 int i;
1498
1499 if (pid <= 0)
1500 return NULL;
1501
1502 for (i = 0; i < tcbtabsize; i++) {
1503 struct tcb *tcp = tcbtab[i];
1504 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1505 return tcp;
1506 }
1507
1508 return NULL;
1509}
1510
1511#ifdef USE_PROCFS
1512
1513static struct tcb *
1514first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515{
1516 int i;
1517 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001518 for (i = 0; i < tcbtabsize; i++) {
1519 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520 if (tcp->flags & TCB_INUSE)
1521 return tcp;
1522 }
1523 return NULL;
1524}
1525
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001527pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528{
1529 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530
Roland McGrathca16be82003-01-10 19:55:28 +00001531 for (i = 0; i < tcbtabsize; i++) {
1532 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533 if (tcp->pfd != pfd)
1534 continue;
1535 if (tcp->flags & TCB_INUSE)
1536 return tcp;
1537 }
1538 return NULL;
1539}
1540
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001541#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542
1543void
Denys Vlasenko12014262011-05-30 14:00:14 +02001544droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545{
1546 if (tcp->pid == 0)
1547 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001548#ifdef TCB_CLONE_THREAD
1549 if (tcp->nclone_threads > 0) {
1550 /* There are other threads left in this process, but this
1551 is the one whose PID represents the whole process.
1552 We need to keep this record around as a zombie until
1553 all the threads die. */
1554 tcp->flags |= TCB_EXITING;
1555 return;
1556 }
1557#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001559 if (debug)
1560 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001562
Roland McGrathe29341c2003-01-10 20:14:20 +00001563 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001564#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001565 if (tcp->flags & TCB_CLONE_THREAD)
1566 tcp->parent->nclone_threads--;
1567#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001568#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001569 /* Update fields like NCLONE_DETACHED, only
1570 for zombie group leader that has already reported
1571 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001572 function. The same condition as at the top of DETACH. */
1573 if ((tcp->flags & TCB_CLONE_THREAD) &&
1574 tcp->parent->nclone_threads == 0 &&
1575 (tcp->parent->flags & TCB_EXITING))
1576 droptcb(tcp->parent);
1577#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001578 tcp->parent = NULL;
1579 }
1580
1581 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 if (tcp->pfd != -1) {
1583 close(tcp->pfd);
1584 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001585#ifdef FREEBSD
1586 if (tcp->pfd_reg != -1) {
1587 close(tcp->pfd_reg);
1588 tcp->pfd_reg = -1;
1589 }
1590 if (tcp->pfd_status != -1) {
1591 close(tcp->pfd_status);
1592 tcp->pfd_status = -1;
1593 }
Roland McGrath553a6092002-12-16 20:40:39 +00001594#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001595#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001596 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597#endif
1598 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001599
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001600 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001602
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603 tcp->outf = 0;
1604}
1605
Roland McGrath0a463882007-07-05 18:43:16 +00001606/* detach traced process; continue with sig
1607 Never call DETACH twice on the same process as both unattached and
1608 attached-unstopped processes give the same ESRCH. For unattached process we
1609 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610
1611static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001612detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613{
1614 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001615#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001616 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001617 struct tcb *zombie = NULL;
1618
1619 /* If the group leader is lingering only because of this other
1620 thread now dying, then detach the leader as well. */
1621 if ((tcp->flags & TCB_CLONE_THREAD) &&
1622 tcp->parent->nclone_threads == 1 &&
1623 (tcp->parent->flags & TCB_EXITING))
1624 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001625#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626
1627 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001628 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629
1630#ifdef LINUX
1631 /*
1632 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001633 * before detaching. Arghh. We go through hoops
1634 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001636#if defined(SPARC)
1637#undef PTRACE_DETACH
1638#define PTRACE_DETACH PTRACE_SUNDETACH
1639#endif
Roland McGrath02203312007-06-11 22:06:31 +00001640 /*
1641 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1642 * expected SIGSTOP. We must catch exactly one as otherwise the
1643 * detached process would be left stopped (process state T).
1644 */
1645 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1647 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001648 }
1649 else if (errno != ESRCH) {
1650 /* Shouldn't happen. */
1651 perror("detach: ptrace(PTRACE_DETACH, ...)");
1652 }
Roland McGrath134813a2007-06-02 00:07:33 +00001653 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1654 : tcp->pid),
1655 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001656 if (errno != ESRCH)
1657 perror("detach: checking sanity");
1658 }
Roland McGrath02203312007-06-11 22:06:31 +00001659 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1660 ? tcp->parent->pid : tcp->pid),
1661 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001662 if (errno != ESRCH)
1663 perror("detach: stopping child");
1664 }
Roland McGrath02203312007-06-11 22:06:31 +00001665 else
1666 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001667 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001669#ifdef __WALL
1670 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1671 if (errno == ECHILD) /* Already gone. */
1672 break;
1673 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001674 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001675 break;
1676 }
1677#endif /* __WALL */
1678 /* No __WALL here. */
1679 if (waitpid(tcp->pid, &status, 0) < 0) {
1680 if (errno != ECHILD) {
1681 perror("detach: waiting");
1682 break;
1683 }
1684#ifdef __WCLONE
1685 /* If no processes, try clones. */
1686 if (wait4(tcp->pid, &status, __WCLONE,
1687 NULL) < 0) {
1688 if (errno != ECHILD)
1689 perror("detach: waiting");
1690 break;
1691 }
1692#endif /* __WCLONE */
1693 }
1694#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001695 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001696#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001697 if (!WIFSTOPPED(status)) {
1698 /* Au revoir, mon ami. */
1699 break;
1700 }
1701 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001702 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 break;
1704 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001705 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001706 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001707 : WSTOPSIG(status));
1708 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001711 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001712#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713
1714#if defined(SUNOS4)
1715 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1716 if (sig && kill(tcp->pid, sig) < 0)
1717 perror("detach: kill");
1718 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001719 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720#endif /* SUNOS4 */
1721
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722 if (!qflag)
1723 fprintf(stderr, "Process %u detached\n", tcp->pid);
1724
1725 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001726
1727#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001728 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001729 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001730 droptcb(zombie);
1731 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001732#endif
1733
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 return error;
1735}
1736
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001737#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001738
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001739static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001740{
1741 int pid;
1742 int status;
1743
1744 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 }
1746}
1747
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001748#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749
1750static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001751cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752{
1753 int i;
1754 struct tcb *tcp;
1755
Roland McGrathee9d4352002-12-18 04:16:10 +00001756 for (i = 0; i < tcbtabsize; i++) {
1757 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758 if (!(tcp->flags & TCB_INUSE))
1759 continue;
1760 if (debug)
1761 fprintf(stderr,
1762 "cleanup: looking at pid %u\n", tcp->pid);
1763 if (tcp_last &&
1764 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001765 tprintf(" <unfinished ...>");
1766 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 }
1768 if (tcp->flags & TCB_ATTACHED)
1769 detach(tcp, 0);
1770 else {
1771 kill(tcp->pid, SIGCONT);
1772 kill(tcp->pid, SIGTERM);
1773 }
1774 }
1775 if (cflag)
1776 call_summary(outf);
1777}
1778
1779static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001780interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781{
1782 interrupted = 1;
1783}
1784
1785#ifndef HAVE_STRERROR
1786
Roland McGrath6d2b3492002-12-30 00:51:30 +00001787#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788extern int sys_nerr;
1789extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001790#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791
1792const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001793strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794{
1795 static char buf[64];
1796
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001797 if (err_no < 1 || err_no >= sys_nerr) {
1798 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799 return buf;
1800 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001801 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802}
1803
1804#endif /* HAVE_STERRROR */
1805
1806#ifndef HAVE_STRSIGNAL
1807
Roland McGrath8f474e02003-01-14 07:53:33 +00001808#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001809extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001811#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1812extern char *_sys_siglist[];
1813#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001814
1815const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001816strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001817{
1818 static char buf[64];
1819
1820 if (sig < 1 || sig >= NSIG) {
1821 sprintf(buf, "Unknown signal %d", sig);
1822 return buf;
1823 }
1824#ifdef HAVE__SYS_SIGLIST
1825 return _sys_siglist[sig];
1826#else
1827 return sys_siglist[sig];
1828#endif
1829}
1830
1831#endif /* HAVE_STRSIGNAL */
1832
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001833#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834
1835static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001836rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837{
1838 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839
Roland McGrathee9d4352002-12-18 04:16:10 +00001840 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001841 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001842 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001843 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001844 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001845 }
1846
Roland McGrathca16be82003-01-10 19:55:28 +00001847 for (i = j = 0; i < tcbtabsize; i++) {
1848 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001849 if (!(tcp->flags & TCB_INUSE))
1850 continue;
1851 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001852 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001853 j++;
1854 }
1855 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001856 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 }
1858}
1859
1860#ifndef HAVE_POLLABLE_PROCFS
1861
1862static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001863proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 int i;
1866
1867 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001868 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869 }
1870 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001871 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872 }
1873}
1874
1875static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001876proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877{
1878 int i;
1879 int n;
1880 struct proc_pollfd pollinfo;
1881
1882 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1883 return n;
1884 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001885 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 }
1887 for (i = 0; i < nprocs; i++) {
1888 if (pollv[i].fd == pollinfo.fd)
1889 pollv[i].revents = pollinfo.revents;
1890 else
1891 pollv[i].revents = 0;
1892 }
1893 poller_pid = pollinfo.pid;
1894 return 1;
1895}
1896
1897static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001898wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899{
1900}
1901
1902static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001903proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904{
1905 struct proc_pollfd pollinfo;
1906 struct sigaction sa;
1907 sigset_t blocked_set, empty_set;
1908 int i;
1909 int n;
1910 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001911#ifdef FREEBSD
1912 struct procfs_status pfs;
1913#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914
1915 switch (fork()) {
1916 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001917 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001918 case 0:
1919 break;
1920 default:
1921 return;
1922 }
1923
1924 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1925 sa.sa_flags = 0;
1926 sigemptyset(&sa.sa_mask);
1927 sigaction(SIGHUP, &sa, NULL);
1928 sigaction(SIGINT, &sa, NULL);
1929 sigaction(SIGQUIT, &sa, NULL);
1930 sigaction(SIGPIPE, &sa, NULL);
1931 sigaction(SIGTERM, &sa, NULL);
1932 sa.sa_handler = wakeup_handler;
1933 sigaction(SIGUSR1, &sa, NULL);
1934 sigemptyset(&blocked_set);
1935 sigaddset(&blocked_set, SIGUSR1);
1936 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1937 sigemptyset(&empty_set);
1938
1939 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001940 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001941 }
1942 n = rl.rlim_cur;
1943 for (i = 0; i < n; i++) {
1944 if (i != pfd && i != proc_poll_pipe[1])
1945 close(i);
1946 }
1947
1948 pollinfo.fd = pfd;
1949 pollinfo.pid = getpid();
1950 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001951#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001952 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1953#else
1954 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1955#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001956 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 switch (errno) {
1958 case EINTR:
1959 continue;
1960 case EBADF:
1961 pollinfo.revents = POLLERR;
1962 break;
1963 case ENOENT:
1964 pollinfo.revents = POLLHUP;
1965 break;
1966 default:
1967 perror("proc_poller: PIOCWSTOP");
1968 }
1969 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1970 _exit(0);
1971 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001972 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001973 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1974 sigsuspend(&empty_set);
1975 }
1976}
1977
1978#endif /* !HAVE_POLLABLE_PROCFS */
1979
1980static int
1981choose_pfd()
1982{
1983 int i, j;
1984 struct tcb *tcp;
1985
1986 static int last;
1987
1988 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001989 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990 /*
1991 * The previous process is ready to run again. We'll
1992 * let it do so if it is currently in a syscall. This
1993 * heuristic improves the readability of the trace.
1994 */
1995 tcp = pfd2tcb(pollv[last].fd);
1996 if (tcp && (tcp->flags & TCB_INSYSCALL))
1997 return pollv[last].fd;
1998 }
1999
2000 for (i = 0; i < nprocs; i++) {
2001 /* Let competing children run round robin. */
2002 j = (i + last + 1) % nprocs;
2003 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2004 tcp = pfd2tcb(pollv[j].fd);
2005 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002006 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002007 }
2008 droptcb(tcp);
2009 return -1;
2010 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002011 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 last = j;
2013 return pollv[j].fd;
2014 }
2015 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002016 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017}
2018
2019static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002020trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002022#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002023 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002024#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 struct tcb *tcp;
2026 int pfd;
2027 int what;
2028 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002029 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002030
2031 for (;;) {
2032 if (interactive)
2033 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2034
2035 if (nprocs == 0)
2036 break;
2037
2038 switch (nprocs) {
2039 case 1:
2040#ifndef HAVE_POLLABLE_PROCFS
2041 if (proc_poll_pipe[0] == -1) {
2042#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002043 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044 if (!tcp)
2045 continue;
2046 pfd = tcp->pfd;
2047 if (pfd == -1)
2048 continue;
2049 break;
2050#ifndef HAVE_POLLABLE_PROCFS
2051 }
2052 /* fall through ... */
2053#endif /* !HAVE_POLLABLE_PROCFS */
2054 default:
2055#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002056#ifdef POLL_HACK
2057 /* On some systems (e.g. UnixWare) we get too much ugly
2058 "unfinished..." stuff when multiple proceses are in
2059 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002060
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002061 if (in_syscall) {
2062 struct pollfd pv;
2063 tcp = in_syscall;
2064 in_syscall = NULL;
2065 pv.fd = tcp->pfd;
2066 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002067 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002068 if (interrupted)
2069 return 0;
2070 continue;
2071 }
2072 else if (what == 1 && pv.revents & POLLWANT) {
2073 goto FOUND;
2074 }
2075 }
2076#endif
2077
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 if (poll(pollv, nprocs, INFTIM) < 0) {
2079 if (interrupted)
2080 return 0;
2081 continue;
2082 }
2083#else /* !HAVE_POLLABLE_PROCFS */
2084 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2085 if (interrupted)
2086 return 0;
2087 continue;
2088 }
2089#endif /* !HAVE_POLLABLE_PROCFS */
2090 pfd = choose_pfd();
2091 if (pfd == -1)
2092 continue;
2093 break;
2094 }
2095
2096 /* Look up `pfd' in our table. */
2097 if ((tcp = pfd2tcb(pfd)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002098 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002099 }
John Hughesb6643082002-05-23 11:02:22 +00002100#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002101 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002102#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002103 /* Get the status of the process. */
2104 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002105#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002106 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002107#else /* FREEBSD */
2108 /* Thanks to some scheduling mystery, the first poller
2109 sometimes waits for the already processed end of fork
2110 event. Doing a non blocking poll here solves the problem. */
2111 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002112 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002113 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002114 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002115#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 ioctl_errno = errno;
2117#ifndef HAVE_POLLABLE_PROCFS
2118 if (proc_poll_pipe[0] != -1) {
2119 if (ioctl_result < 0)
2120 kill(poller_pid, SIGKILL);
2121 else
2122 kill(poller_pid, SIGUSR1);
2123 }
2124#endif /* !HAVE_POLLABLE_PROCFS */
2125 }
2126 if (interrupted)
2127 return 0;
2128
2129 if (interactive)
2130 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2131
2132 if (ioctl_result < 0) {
2133 /* Find out what happened if it failed. */
2134 switch (ioctl_errno) {
2135 case EINTR:
2136 case EBADF:
2137 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138#ifdef FREEBSD
2139 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002140#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002141 case ENOENT:
2142 droptcb(tcp);
2143 continue;
2144 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002145 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 }
2147 }
2148
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002149#ifdef FREEBSD
2150 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2151 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002152 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002153 continue;
2154 }
Roland McGrath553a6092002-12-16 20:40:39 +00002155#endif
2156
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 /* clear the just started flag */
2158 tcp->flags &= ~TCB_STARTUP;
2159
2160 /* set current output file */
2161 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002162 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163
2164 if (cflag) {
2165 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002166#ifdef FREEBSD
2167 char buf[1024];
2168 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002169
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002170 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2171 buf[len] = '\0';
2172 sscanf(buf,
2173 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2174 &stime.tv_sec, &stime.tv_usec);
2175 } else
2176 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002177#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002178 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2179 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002180#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002181 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2182 tcp->stime = stime;
2183 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002184 what = tcp->status.PR_WHAT;
2185 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002186#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002188 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2189 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002191 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192 }
2193 }
2194 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002195#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002197#ifdef POLL_HACK
2198 in_syscall = tcp;
2199#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 case PR_SYSEXIT:
2201 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002202 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 }
2204 break;
2205 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002206 if (cflag != CFLAG_ONLY_STATS
2207 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208 printleader(tcp);
2209 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002210 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002211 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002212#ifdef PR_INFO
2213 if (tcp->status.PR_INFO.si_signo == what) {
2214 printleader(tcp);
2215 tprintf(" siginfo=");
2216 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002217 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002218 }
2219#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002220 }
2221 break;
2222 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002223 if (cflag != CFLAGS_ONLY_STATS
2224 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002225 printleader(tcp);
2226 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002227 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002228 }
2229 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002230#ifdef FREEBSD
2231 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002232 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002233#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002235 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 break;
2237 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002238 /* Remember current print column before continuing. */
2239 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002240 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002241#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002242 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002243#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002244 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002245#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002246 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002247 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248 }
2249 }
2250 return 0;
2251}
2252
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002253#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002254
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002255#ifdef TCB_GROUP_EXITING
2256/* Handle an exit detach or death signal that is taking all the
2257 related clone threads with it. This is called in three circumstances:
2258 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2259 SIG == 0 Continuing TCP will perform an exit_group syscall.
2260 SIG == other Continuing TCP with SIG will kill the process.
2261*/
2262static int
2263handle_group_exit(struct tcb *tcp, int sig)
2264{
2265 /* We need to locate our records of all the clone threads
2266 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002267 struct tcb *leader = NULL;
2268
2269 if (tcp->flags & TCB_CLONE_THREAD)
2270 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002271
2272 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002273 if (leader != NULL && leader != tcp
2274 && !(leader->flags & TCB_GROUP_EXITING)
2275 && !(tcp->flags & TCB_STARTUP)
2276 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002277 fprintf(stderr,
2278 "PANIC: handle_group_exit: %d leader %d\n",
2279 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002280 }
2281 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002282 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002283 }
2284 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002285 /* Mark that we are taking the process down. */
2286 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002287 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002288 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002289 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002290 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002291 } else {
2292 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2293 cleanup();
2294 return -1;
2295 }
2296 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002297 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002298 if (leader != tcp)
2299 droptcb(tcp);
2300 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002301 /* The leader will report to us as parent now,
2302 and then we'll get to the SIG==-1 case. */
2303 return 0;
2304 }
2305 }
2306
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002307 return 0;
2308}
2309#endif
2310
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002311#ifdef LINUX
2312static int
2313handle_ptrace_event(int status, struct tcb *tcp)
2314{
2315 if (status >> 16 == PTRACE_EVENT_VFORK ||
2316 status >> 16 == PTRACE_EVENT_CLONE ||
2317 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002318 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002319
2320 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2321 if (errno != ESRCH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002322 error_msg_and_die("Cannot get new child's pid");
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002323 }
2324 return -1;
2325 }
2326 return handle_new_child(tcp, childpid, 0);
2327 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002328 if (status >> 16 == PTRACE_EVENT_EXEC) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002329 return 0;
2330 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002331 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2332 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002333 return 1;
2334}
2335#endif
2336
Roland McGratheb9e2e82009-06-02 16:49:22 -07002337static int
2338trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002339{
2340 int pid;
2341 int wait_errno;
2342 int status;
2343 struct tcb *tcp;
2344#ifdef LINUX
2345 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002346#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002347 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002348#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349#endif /* LINUX */
2350
Roland McGratheb9e2e82009-06-02 16:49:22 -07002351 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002352 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002353 return 0;
2354 if (interactive)
2355 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002356#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002357#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002358 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002359 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002360 /* this kernel does not support __WALL */
2361 wait4_options &= ~__WALL;
2362 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002363 pid = wait4(-1, &status, wait4_options,
2364 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002365 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002366 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002367 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002368 pid = wait4(-1, &status, __WCLONE,
2369 cflag ? &ru : NULL);
2370 if (pid == -1) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002371 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002372 }
2373 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002374#else
2375 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2376#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002377#endif /* LINUX */
2378#ifdef SUNOS4
2379 pid = wait(&status);
2380#endif /* SUNOS4 */
2381 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002382 if (interactive)
2383 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002384
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002386 switch (wait_errno) {
2387 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002389 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390 /*
2391 * We would like to verify this case
2392 * but sometimes a race in Solbourne's
2393 * version of SunOS sometimes reports
2394 * ECHILD before sending us SIGCHILD.
2395 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002396 return 0;
2397 default:
2398 errno = wait_errno;
2399 perror("strace: wait");
2400 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002401 }
2402 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002403 if (pid == popen_pid) {
2404 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002405 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002406 continue;
2407 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002408 if (debug) {
2409 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2410#ifdef LINUX
2411 unsigned ev = (unsigned)status >> 16;
2412 if (ev) {
2413 static const char *const event_names[] = {
2414 [PTRACE_EVENT_CLONE] = "CLONE",
2415 [PTRACE_EVENT_FORK] = "FORK",
2416 [PTRACE_EVENT_VFORK] = "VFORK",
2417 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2418 [PTRACE_EVENT_EXEC] = "EXEC",
2419 [PTRACE_EVENT_EXIT] = "EXIT",
2420 };
2421 const char *e;
2422 if (ev < ARRAY_SIZE(event_names))
2423 e = event_names[ev];
2424 else {
2425 sprintf(buf, "?? (%u)", ev);
2426 e = buf;
2427 }
2428 fprintf(stderr, " PTRACE_EVENT_%s", e);
2429 }
2430#endif
2431 strcpy(buf, "???");
2432 if (WIFSIGNALED(status))
2433#ifdef WCOREDUMP
2434 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2435 WCOREDUMP(status) ? "core," : "",
2436 signame(WTERMSIG(status)));
2437#else
2438 sprintf(buf, "WIFSIGNALED,sig=%s",
2439 signame(WTERMSIG(status)));
2440#endif
2441 if (WIFEXITED(status))
2442 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2443 if (WIFSTOPPED(status))
2444 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
2445 if (WIFCONTINUED(status))
2446 strcpy(buf, "WIFCONTINUED");
2447 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2448 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449
2450 /* Look up `pid' in our table. */
2451 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002452#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002453 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002454 /* This is needed to go with the CLONE_PTRACE
2455 changes in process.c/util.c: we might see
2456 the child's initial trap before we see the
2457 parent return from the clone syscall.
2458 Leave the child suspended until the parent
2459 returns from its system call. Only then
2460 will we have the association of parent and
2461 child so that we know how to do clearbpt
2462 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002463 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002464 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002465 if (!qflag)
2466 fprintf(stderr, "\
2467Process %d attached (waiting for parent)\n",
2468 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002469 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002470 else
2471 /* This can happen if a clone call used
2472 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002473#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002474 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002475 if (WIFSTOPPED(status))
2476 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002477 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002478 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002480 /* set current output file */
2481 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002482 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002483 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002484#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002485 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2486 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002487#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002489
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002490 if (tcp->flags & TCB_SUSPENDED) {
2491 /*
2492 * Apparently, doing any ptrace() call on a stopped
2493 * process, provokes the kernel to report the process
2494 * status again on a subsequent wait(), even if the
2495 * process has not been actually restarted.
2496 * Since we have inspected the arguments of suspended
2497 * processes we end up here testing for this case.
2498 */
2499 continue;
2500 }
2501 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002502 if (pid == strace_child)
2503 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002504 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002505 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2506 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002507 tprintf("+++ killed by %s %s+++",
2508 signame(WTERMSIG(status)),
2509#ifdef WCOREDUMP
2510 WCOREDUMP(status) ? "(core dumped) " :
2511#endif
2512 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002513 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002514 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002515#ifdef TCB_GROUP_EXITING
2516 handle_group_exit(tcp, -1);
2517#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002518 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002519#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002520 continue;
2521 }
2522 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002523 if (pid == strace_child)
2524 exit_code = WEXITSTATUS(status);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002525 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002526#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002527 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002528 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002529#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002530 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002531 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002532 "PANIC: attached pid %u exited with %d\n",
2533 pid, WEXITSTATUS(status));
2534 }
Roland McGrath0a396902003-06-10 03:05:53 +00002535 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002536 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002537 tprintf(" <unfinished ... exit status %d>\n",
2538 WEXITSTATUS(status));
2539 tcp_last = NULL;
2540 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002541#ifdef TCB_GROUP_EXITING
2542 handle_group_exit(tcp, -1);
2543#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002545#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 continue;
2547 }
2548 if (!WIFSTOPPED(status)) {
2549 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2550 droptcb(tcp);
2551 continue;
2552 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002554 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002555 if (handle_ptrace_event(status, tcp) != 1)
2556 goto tracing;
2557 }
2558
Roland McGrath02203312007-06-11 22:06:31 +00002559 /*
2560 * Interestingly, the process may stop
2561 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002562 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002563 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002564 * A no-MMU vforked child won't send up a signal,
2565 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002566 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002567 if ((tcp->flags & TCB_STARTUP) &&
2568 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002569 /*
2570 * This flag is there to keep us in sync.
2571 * Next time this process stops it should
2572 * really be entering a system call.
2573 */
2574 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002575 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002576 /*
2577 * One example is a breakpoint inherited from
2578 * parent through fork ().
2579 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002580 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2581 droptcb(tcp);
2582 cleanup();
2583 return -1;
2584 }
2585 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002586#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002587 /* If options were not set for this tracee yet */
2588 if (tcp->parent == NULL) {
2589 if (ptrace_setoptions) {
2590 if (debug)
2591 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2592 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2593 if (errno != ESRCH) {
2594 /* Should never happen, really */
2595 perror_msg_and_die("PTRACE_SETOPTIONS");
2596 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002597 }
2598 }
2599 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002600#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002601 goto tracing;
2602 }
2603
Denys Vlasenko75422762011-05-27 14:36:01 +02002604 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 if (WSTOPSIG(status) == SIGSTOP &&
2606 (tcp->flags & TCB_SIGTRAPPED)) {
2607 /*
2608 * Trapped attempt to block SIGTRAP
2609 * Hope we are back in control now.
2610 */
2611 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002612 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613 cleanup();
2614 return -1;
2615 }
2616 continue;
2617 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002618 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002620 siginfo_t si;
2621#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002622 long pc = 0;
2623 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002624
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002625 upeek(tcp, PT_CR_IPSR, &psr);
2626 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002627
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002628# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002629 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002630# define PC_FORMAT_STR " @ %lx"
2631# define PC_FORMAT_ARG pc
2632#else
2633# define PC_FORMAT_STR "%s"
2634# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002635#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002637 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2638 tprintf("--- ");
2639 printsiginfo(&si, verbose(tcp));
2640 tprintf(" (%s)" PC_FORMAT_STR " ---",
2641 strsignal(WSTOPSIG(status)),
2642 PC_FORMAT_ARG);
2643 } else
2644 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2645 strsignal(WSTOPSIG(status)),
2646 signame(WSTOPSIG(status)),
2647 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002648 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002649 }
Roland McGrath05690952004-10-20 01:00:27 +00002650 if (((tcp->flags & TCB_ATTACHED) ||
2651 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002652 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002653#ifdef TCB_GROUP_EXITING
2654 handle_group_exit(tcp, WSTOPSIG(status));
2655#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002656 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002657#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002658 continue;
2659 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002660 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 cleanup();
2662 return -1;
2663 }
2664 tcp->flags &= ~TCB_SUSPENDED;
2665 continue;
2666 }
Roland McGrath02203312007-06-11 22:06:31 +00002667 /* we handled the STATUS, we are permitted to interrupt now. */
2668 if (interrupted)
2669 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002670 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2671 /* ptrace() failed in trace_syscall() with ESRCH.
2672 * Likely a result of process disappearing mid-flight.
2673 * Observed case: exit_group() terminating
2674 * all processes in thread group. In this case, threads
2675 * "disappear" in an unpredictable moment without any
2676 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002677 */
2678 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002679 if (tcp_last) {
2680 /* Do we have dangling line "syscall(param, param"?
2681 * Finish the line then. We cannot
2682 */
2683 tcp_last->flags |= TCB_REPRINT;
2684 tprintf(" <unfinished ...>");
2685 printtrailer();
2686 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002687 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002688 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002689 ptrace(PTRACE_KILL,
2690 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 droptcb(tcp);
2692 }
2693 continue;
2694 }
2695 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002696#ifdef TCB_GROUP_EXITING
2697 if (tcp->flags & TCB_GROUP_EXITING) {
2698 if (handle_group_exit(tcp, 0) < 0)
2699 return -1;
2700 continue;
2701 }
2702#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002703 if (tcp->flags & TCB_ATTACHED)
2704 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002705 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706 cleanup();
2707 return -1;
2708 }
2709 continue;
2710 }
2711 if (tcp->flags & TCB_SUSPENDED) {
2712 if (!qflag)
2713 fprintf(stderr, "Process %u suspended\n", pid);
2714 continue;
2715 }
2716 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002717 /* Remember current print column before continuing. */
2718 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002719 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002720 cleanup();
2721 return -1;
2722 }
2723 }
2724 return 0;
2725}
2726
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002727#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002728
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002729#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002730
2731void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002732tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002733{
2734 va_list args;
2735
Andreas Schwabe5355de2009-10-27 16:56:43 +01002736 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002737 if (outf) {
2738 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002739 if (n < 0) {
2740 if (outf != stderr)
2741 perror(outfname == NULL
2742 ? "<writing to pipe>" : outfname);
2743 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002744 curcol += n;
2745 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002746 va_end(args);
2747 return;
2748}
2749
2750void
Denys Vlasenko12014262011-05-30 14:00:14 +02002751printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002752{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002753 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002754 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002755 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002756 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002757 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002758 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002759 tprintf("= ? <unavailable>\n");
2760 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002761 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002762 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002763 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002764 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002765 }
2766 curcol = 0;
2767 if ((followfork == 1 || pflag_seen > 1) && outfname)
2768 tprintf("%-5d ", tcp->pid);
2769 else if (nprocs > 1 && !outfname)
2770 tprintf("[pid %5u] ", tcp->pid);
2771 if (tflag) {
2772 char str[sizeof("HH:MM:SS")];
2773 struct timeval tv, dtv;
2774 static struct timeval otv;
2775
2776 gettimeofday(&tv, NULL);
2777 if (rflag) {
2778 if (otv.tv_sec == 0)
2779 otv = tv;
2780 tv_sub(&dtv, &tv, &otv);
2781 tprintf("%6ld.%06ld ",
2782 (long) dtv.tv_sec, (long) dtv.tv_usec);
2783 otv = tv;
2784 }
2785 else if (tflag > 2) {
2786 tprintf("%ld.%06ld ",
2787 (long) tv.tv_sec, (long) tv.tv_usec);
2788 }
2789 else {
2790 time_t local = tv.tv_sec;
2791 strftime(str, sizeof(str), "%T", localtime(&local));
2792 if (tflag > 1)
2793 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2794 else
2795 tprintf("%s ", str);
2796 }
2797 }
2798 if (iflag)
2799 printcall(tcp);
2800}
2801
2802void
Denys Vlasenko12014262011-05-30 14:00:14 +02002803tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002804{
2805 if (curcol < col)
2806 tprintf("%*s", col - curcol, "");
2807}
2808
2809void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002810printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002811{
2812 tprintf("\n");
2813 tcp_last = NULL;
2814}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002815
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002816#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002817
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002818int
2819mp_ioctl(int fd, int cmd, void *arg, int size)
2820{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002821 struct iovec iov[2];
2822 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002823
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002824 iov[0].iov_base = &cmd;
2825 iov[0].iov_len = sizeof cmd;
2826 if (arg) {
2827 ++n;
2828 iov[1].iov_base = arg;
2829 iov[1].iov_len = size;
2830 }
Roland McGrath553a6092002-12-16 20:40:39 +00002831
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002832 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002833}
2834
2835#endif