blob: 0b823606f41bb443964b8c414c60a783bbb2f3cd [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;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200121static uid_t run_uid;
122static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123
124int acolumn = DEFAULT_ACOLUMN;
125int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200129static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200130static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200131static const 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 Vlasenkof95397a2011-06-24 16:51:16 +0200474 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000475 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200476 if (debug)
477 fprintf(stderr, "attach to pid %d failed\n", tid);
478 }
479 else {
480 if (debug)
481 fprintf(stderr, "attach to pid %d succeeded\n", tid);
482 if (tid != tcbtab[tcbi]->pid) {
483 tcp = alloctcb(tid);
484 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD;
485 tcbtab[tcbi]->nclone_threads++;
486 tcp->parent = tcbtab[tcbi];
487 }
Roland McGrath02203312007-06-11 22:06:31 +0000488 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000489 if (interactive) {
490 sigprocmask(SIG_SETMASK, &empty_set, NULL);
491 if (interrupted)
492 return;
493 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
494 }
Roland McGrath02203312007-06-11 22:06:31 +0000495 }
496 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000497 ntid -= nerr;
498 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000499 perror("attach: ptrace(PTRACE_ATTACH, ...)");
500 droptcb(tcp);
501 continue;
502 }
503 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000504 fprintf(stderr, ntid > 1
505? "Process %u attached with %u threads - interrupt to quit\n"
506: "Process %u attached - interrupt to quit\n",
507 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000508 }
509 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000510 } /* if (opendir worked) */
511 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000512# endif
513 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
514 perror("attach: ptrace(PTRACE_ATTACH, ...)");
515 droptcb(tcp);
516 continue;
517 }
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200518 if (debug)
519 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000520
521 if (daemonized_tracer) {
522 /*
523 * It is our grandparent we trace, not a -p PID.
524 * Don't want to just detach on exit, so...
525 */
526 tcp->flags &= ~TCB_ATTACHED;
527 /*
528 * Make parent go away.
529 * Also makes grandparent's wait() unblock.
530 */
531 kill(getppid(), SIGKILL);
532 }
533
Roland McGrath02203312007-06-11 22:06:31 +0000534#endif /* !USE_PROCFS */
535 if (!qflag)
536 fprintf(stderr,
537 "Process %u attached - interrupt to quit\n",
538 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200539 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000540
541 if (interactive)
542 sigprocmask(SIG_SETMASK, &empty_set, NULL);
543}
544
545static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200546startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000547{
548 struct stat statbuf;
549 const char *filename;
550 char pathname[MAXPATHLEN];
551 int pid = 0;
552 struct tcb *tcp;
553
554 filename = argv[0];
555 if (strchr(filename, '/')) {
556 if (strlen(filename) > sizeof pathname - 1) {
557 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200558 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000559 }
560 strcpy(pathname, filename);
561 }
562#ifdef USE_DEBUGGING_EXEC
563 /*
564 * Debuggers customarily check the current directory
565 * first regardless of the path but doing that gives
566 * security geeks a panic attack.
567 */
568 else if (stat(filename, &statbuf) == 0)
569 strcpy(pathname, filename);
570#endif /* USE_DEBUGGING_EXEC */
571 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000572 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000573 int m, n, len;
574
575 for (path = getenv("PATH"); path && *path; path += m) {
576 if (strchr(path, ':')) {
577 n = strchr(path, ':') - path;
578 m = n + 1;
579 }
580 else
581 m = n = strlen(path);
582 if (n == 0) {
583 if (!getcwd(pathname, MAXPATHLEN))
584 continue;
585 len = strlen(pathname);
586 }
587 else if (n > sizeof pathname - 1)
588 continue;
589 else {
590 strncpy(pathname, path, n);
591 len = n;
592 }
593 if (len && pathname[len - 1] != '/')
594 pathname[len++] = '/';
595 strcpy(pathname + len, filename);
596 if (stat(pathname, &statbuf) == 0 &&
597 /* Accept only regular files
598 with some execute bits set.
599 XXX not perfect, might still fail */
600 S_ISREG(statbuf.st_mode) &&
601 (statbuf.st_mode & 0111))
602 break;
603 }
604 }
605 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200606 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000607 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000608 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000609 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200610 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000611 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200612 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
613 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000614 ) {
615 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000616#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200617 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000618#ifdef MIPS
619 /* Kludge for SGI, see proc_open for details. */
620 sa.sa_handler = foobar;
621 sa.sa_flags = 0;
622 sigemptyset(&sa.sa_mask);
623 sigaction(SIGINT, &sa, NULL);
624#endif /* MIPS */
625#ifndef FREEBSD
626 pause();
627#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000628 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000629#endif /* FREEBSD */
630#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200631 if (outf != stderr)
632 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000633
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000634 if (!daemonized_tracer) {
635 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200636 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000637 }
638 if (debug)
639 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000640 }
Roland McGrath02203312007-06-11 22:06:31 +0000641
642 if (username != NULL || geteuid() == 0) {
643 uid_t run_euid = run_uid;
644 gid_t run_egid = run_gid;
645
646 if (statbuf.st_mode & S_ISUID)
647 run_euid = statbuf.st_uid;
648 if (statbuf.st_mode & S_ISGID)
649 run_egid = statbuf.st_gid;
650
651 /*
652 * It is important to set groups before we
653 * lose privileges on setuid.
654 */
655 if (username != NULL) {
656 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200657 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000658 }
659 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200660 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000661 }
662 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200663 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000664 }
665 }
666 }
667 else
668 setreuid(run_uid, run_uid);
669
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000670 if (!daemonized_tracer) {
671 /*
672 * Induce an immediate stop so that the parent
673 * will resume us with PTRACE_SYSCALL and display
674 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400675 * Unless of course we're on a no-MMU system where
676 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400678 if (!strace_vforked)
679 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000680 } else {
681 struct sigaction sv_sigchld;
682 sigaction(SIGCHLD, NULL, &sv_sigchld);
683 /*
684 * Make sure it is not SIG_IGN, otherwise wait
685 * will not block.
686 */
687 signal(SIGCHLD, SIG_DFL);
688 /*
689 * Wait for grandchild to attach to us.
690 * It kills child after that, and wait() unblocks.
691 */
692 alarm(3);
693 wait(NULL);
694 alarm(0);
695 sigaction(SIGCHLD, &sv_sigchld, NULL);
696 }
Roland McGrath02203312007-06-11 22:06:31 +0000697#endif /* !USE_PROCFS */
698
699 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200700 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000701 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000702
703 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200704 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
705 strace_tracer_pid = getpid();
706
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000707 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708 if (daemonized_tracer) {
709 /* We want subsequent startup_attach() to attach to it. */
710 tcp->flags |= TCB_ATTACHED;
711 }
Roland McGrath02203312007-06-11 22:06:31 +0000712#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000713 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200714 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000715 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000716#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000717}
718
Wang Chaob13c0de2010-11-12 17:25:19 +0800719#ifdef LINUX
720/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000721 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800722 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000723 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800724 */
725static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200726test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800727{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000728 int pid, expected_grandchild = 0, found_grandchild = 0;
729 const unsigned int test_options = PTRACE_O_TRACECLONE |
730 PTRACE_O_TRACEFORK |
731 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800732
733 if ((pid = fork()) < 0)
734 return -1;
735 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000736 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800737 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800738 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000739 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800740 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000741
742 while (1) {
743 int status, tracee_pid;
744
745 tracee_pid = wait(&status);
746 if (tracee_pid == -1) {
747 if (errno == EINTR)
748 continue;
749 else if (errno == ECHILD)
750 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200751 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000752 return -1;
753 }
754 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000755 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000756 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
757 errno != ESRCH)
758 kill(tracee_pid, SIGKILL);
759 }
760 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000761 switch (WSTOPSIG(status)) {
762 case SIGSTOP:
763 if (ptrace(PTRACE_SETOPTIONS, pid,
764 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000765 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800766 return -1;
767 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000768 break;
769 case SIGTRAP:
770 if (status >> 16 == PTRACE_EVENT_FORK) {
771 long msg = 0;
772
773 if (ptrace(PTRACE_GETEVENTMSG, pid,
774 NULL, (long) &msg) == 0)
775 expected_grandchild = msg;
776 }
777 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800778 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000779 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
780 errno != ESRCH)
781 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800782 }
783 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000784 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200785 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800786 return 0;
787}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200788
789/*
790 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
791 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
792 * and then see whether it will stop with (SIGTRAP | 0x80).
793 *
794 * Use of this option enables correct handling of user-generated SIGTRAPs,
795 * and SIGTRAPs generated by special instructions such as int3 on x86:
796 * _start: .globl _start
797 * int3
798 * movl $42, %ebx
799 * movl $1, %eax
800 * int $0x80
801 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
802 */
803static void
804test_ptrace_setoptions_for_all(void)
805{
806 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
807 int pid;
808 int it_worked = 0;
809
810 pid = fork();
811 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200812 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200813
814 if (pid == 0) {
815 pid = getpid();
816 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200817 /* Note: exits with exitcode 1 */
818 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200819 kill(pid, SIGSTOP);
820 _exit(0); /* parent should see entry into this syscall */
821 }
822
823 while (1) {
824 int status, tracee_pid;
825
826 errno = 0;
827 tracee_pid = wait(&status);
828 if (tracee_pid <= 0) {
829 if (errno == EINTR)
830 continue;
831 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200832 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200833 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200834 if (WIFEXITED(status)) {
835 if (WEXITSTATUS(status) == 0)
836 break;
837 /* PTRACE_TRACEME failed in child. This is fatal. */
838 exit(1);
839 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200840 if (!WIFSTOPPED(status)) {
841 kill(pid, SIGKILL);
842 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
843 }
844 if (WSTOPSIG(status) == SIGSTOP) {
845 /*
846 * We don't check "options aren't accepted" error.
847 * If it happens, we'll never get (SIGTRAP | 0x80),
848 * and thus will decide to not use the option.
849 * IOW: the outcome of the test will be correct.
850 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200851 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
852 if (errno != EINVAL)
853 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200854 }
855 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
856 it_worked = 1;
857 }
858 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
859 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200860 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200861 }
862 }
863
864 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200865 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200866 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200867 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200868 fprintf(stderr, "ptrace_setoptions = %#x\n",
869 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200870 return;
871 }
872
873 fprintf(stderr,
874 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
875}
Wang Chaob13c0de2010-11-12 17:25:19 +0800876#endif
877
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000879main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000880{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881 struct tcb *tcp;
882 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000883 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884 struct sigaction sa;
885
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000886 progname = argv[0] ? argv[0] : "strace";
887
Denys Vlasenko75422762011-05-27 14:36:01 +0200888 strace_tracer_pid = getpid();
889
Roland McGrathee9d4352002-12-18 04:16:10 +0000890 /* Allocate the initial tcbtab. */
891 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200892 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200893 if (tcbtab == NULL)
894 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200895 tcp = calloc(tcbtabsize, sizeof(*tcp));
896 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200897 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200898 for (c = 0; c < tcbtabsize; c++)
899 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000900
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 outf = stderr;
902 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000903 set_sortby(DEFAULT_SORTBY);
904 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 qualify("trace=all");
906 qualify("abbrev=all");
907 qualify("verbose=all");
908 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000910 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000911#ifndef USE_PROCFS
912 "D"
913#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000914 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000915 switch (c) {
916 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000917 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200918 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000919 }
920 cflag = CFLAG_ONLY_STATS;
921 break;
922 case 'C':
923 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200924 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000925 }
926 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 break;
928 case 'd':
929 debug++;
930 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000931#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000932 case 'D':
933 daemonized_tracer = 1;
934 break;
935#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000936 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000937 optF = 1;
938 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 case 'f':
940 followfork++;
941 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 case 'h':
943 usage(stdout, 0);
944 break;
945 case 'i':
946 iflag++;
947 break;
948 case 'q':
949 qflag++;
950 break;
951 case 'r':
952 rflag++;
953 tflag++;
954 break;
955 case 't':
956 tflag++;
957 break;
958 case 'T':
959 dtime++;
960 break;
961 case 'x':
962 xflag++;
963 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000964 case 'y':
965 show_fd_path = 1;
966 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 case 'v':
968 qualify("abbrev=none");
969 break;
970 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000971 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 exit(0);
973 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000974 case 'z':
975 not_failing_only = 1;
976 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 case 'a':
978 acolumn = atoi(optarg);
979 break;
980 case 'e':
981 qualify(optarg);
982 break;
983 case 'o':
984 outfname = strdup(optarg);
985 break;
986 case 'O':
987 set_overhead(atoi(optarg));
988 break;
989 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000990 if ((pid = atoi(optarg)) <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200991 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992 break;
993 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200994 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200995 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 break;
997 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000998 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 tcp->flags |= TCB_ATTACHED;
1000 pflag_seen++;
1001 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001002 case 'P':
1003 tracing_paths = 1;
1004 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001005 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001006 }
1007 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 case 's':
1009 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001010 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001011 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001012 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 break;
1014 case 'S':
1015 set_sortby(optarg);
1016 break;
1017 case 'u':
1018 username = strdup(optarg);
1019 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001020 case 'E':
1021 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001022 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001023 }
1024 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 default:
1026 usage(stderr, 1);
1027 break;
1028 }
1029 }
1030
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001031 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001032 usage(stderr, 1);
1033
Wang Chaod322a4b2010-08-05 14:30:11 +08001034 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001035 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001036 }
1037
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001038 if (!followfork)
1039 followfork = optF;
1040
Roland McGrathcb9def62006-04-25 07:48:03 +00001041 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001042 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001043 }
1044
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 /* See if they want to run as another user. */
1046 if (username != NULL) {
1047 struct passwd *pent;
1048
1049 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001050 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 }
1052 if ((pent = getpwnam(username)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001053 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 }
1055 run_uid = pent->pw_uid;
1056 run_gid = pent->pw_gid;
1057 }
1058 else {
1059 run_uid = getuid();
1060 run_gid = getgid();
1061 }
1062
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001063#ifdef LINUX
1064 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001065 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001066 fprintf(stderr,
1067 "Test for options supported by PTRACE_SETOPTIONS "
1068 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001069 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001070 }
1071 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001072 fprintf(stderr, "ptrace_setoptions = %#x\n",
1073 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001074 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001075 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001076#endif
1077
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078 /* Check if they want to redirect the output. */
1079 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001080 /* See if they want to pipe the output. */
1081 if (outfname[0] == '|' || outfname[0] == '!') {
1082 /*
1083 * We can't do the <outfname>.PID funny business
1084 * when using popen, so prohibit it.
1085 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001086 if (followfork > 1)
1087 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1088 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001089 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001090 else if (followfork <= 1)
1091 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 }
1093
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001094 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1095 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001097 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001098 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001101 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001102
Roland McGrath54cc1c82007-11-03 23:34:11 +00001103 /* Valid states here:
1104 optind < argc pflag_seen outfname interactive
1105 1 0 0 1
1106 0 1 0 1
1107 1 0 1 0
1108 0 1 1 1
1109 */
1110
1111 /* STARTUP_CHILD must be called before the signal handlers get
1112 installed below as they are inherited into the spawned process.
1113 Also we do not need to be protected by them as during interruption
1114 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1115 if (!pflag_seen)
1116 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 sigemptyset(&empty_set);
1119 sigemptyset(&blocked_set);
1120 sa.sa_handler = SIG_IGN;
1121 sigemptyset(&sa.sa_mask);
1122 sa.sa_flags = 0;
1123 sigaction(SIGTTOU, &sa, NULL);
1124 sigaction(SIGTTIN, &sa, NULL);
1125 if (interactive) {
1126 sigaddset(&blocked_set, SIGHUP);
1127 sigaddset(&blocked_set, SIGINT);
1128 sigaddset(&blocked_set, SIGQUIT);
1129 sigaddset(&blocked_set, SIGPIPE);
1130 sigaddset(&blocked_set, SIGTERM);
1131 sa.sa_handler = interrupt;
1132#ifdef SUNOS4
1133 /* POSIX signals on sunos4.1 are a little broken. */
1134 sa.sa_flags = SA_INTERRUPT;
1135#endif /* SUNOS4 */
1136 }
1137 sigaction(SIGHUP, &sa, NULL);
1138 sigaction(SIGINT, &sa, NULL);
1139 sigaction(SIGQUIT, &sa, NULL);
1140 sigaction(SIGPIPE, &sa, NULL);
1141 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001142#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 sa.sa_handler = reaper;
1144 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001145#else
1146 /* Make sure SIGCHLD has the default action so that waitpid
1147 definitely works without losing track of children. The user
1148 should not have given us a bogus state to inherit, but he might
1149 have. Arguably we should detect SIG_IGN here and pass it on
1150 to children, but probably noone really needs that. */
1151 sa.sa_handler = SIG_DFL;
1152 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001153#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001155 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001156 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001157
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 if (trace() < 0)
1159 exit(1);
1160 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001161 fflush(NULL);
1162 if (exit_code > 0xff) {
1163 /* Child was killed by a signal, mimic that. */
1164 exit_code &= 0xff;
1165 signal(exit_code, SIG_DFL);
1166 raise(exit_code);
1167 /* Paranoia - what if this signal is not fatal?
1168 Exit with 128 + signo then. */
1169 exit_code += 128;
1170 }
1171 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172}
1173
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001174static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001175expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001176{
1177 /* Allocate some more TCBs and expand the table.
1178 We don't want to relocate the TCBs because our
1179 callers have pointers and it would be a pain.
1180 So tcbtab is a table of pointers. Since we never
1181 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001182 int i = tcbtabsize;
1183 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1184 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1185 if (newtab == NULL || newtcbs == NULL)
1186 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001187 tcbtabsize *= 2;
1188 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001189 while (i < tcbtabsize)
1190 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001191}
1192
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001194alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195{
1196 int i;
1197 struct tcb *tcp;
1198
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001199 if (nprocs == tcbtabsize)
1200 expand_tcbtab();
1201
Roland McGrathee9d4352002-12-18 04:16:10 +00001202 for (i = 0; i < tcbtabsize; i++) {
1203 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001205 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 tcp->flags = TCB_INUSE | TCB_STARTUP;
1208 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 tcp->pfd = -1;
1210 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001211 if (debug)
1212 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001213 if (command_options_parsed)
1214 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 return tcp;
1216 }
1217 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001218 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219}
1220
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001221#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001223proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224{
1225 char proc[32];
1226 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001227#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001228 int i;
1229 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230 sigset_t signals;
1231 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001232#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233#ifndef HAVE_POLLABLE_PROCFS
1234 static int last_pfd;
1235#endif
1236
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001237#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001238 /* Open the process pseudo-files in /proc. */
1239 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1240 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 perror("strace: open(\"/proc/...\", ...)");
1242 return -1;
1243 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001244 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001245 sprintf(proc, "/proc/%d/status", tcp->pid);
1246 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1247 perror("strace: open(\"/proc/...\", ...)");
1248 return -1;
1249 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001250 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001251 sprintf(proc, "/proc/%d/as", tcp->pid);
1252 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1253 perror("strace: open(\"/proc/...\", ...)");
1254 return -1;
1255 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001256 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001257#else
1258 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001259#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001260 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001261 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001262#else /* FREEBSD */
1263 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001264 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001265#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001266 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001267 perror("strace: open(\"/proc/...\", ...)");
1268 return -1;
1269 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001270 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001271#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001272#ifdef FREEBSD
1273 sprintf(proc, "/proc/%d/regs", tcp->pid);
1274 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1275 perror("strace: open(\"/proc/.../regs\", ...)");
1276 return -1;
1277 }
1278 if (cflag) {
1279 sprintf(proc, "/proc/%d/status", tcp->pid);
1280 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1281 perror("strace: open(\"/proc/.../status\", ...)");
1282 return -1;
1283 }
1284 } else
1285 tcp->pfd_status = -1;
1286#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001287 rebuild_pollv();
1288 if (!attaching) {
1289 /*
1290 * Wait for the child to pause. Because of a race
1291 * condition we have to poll for the event.
1292 */
1293 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001294 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001295 perror("strace: PIOCSTATUS");
1296 return -1;
1297 }
1298 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001299 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001300 }
1301 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001302#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001303 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001304 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001305 perror("strace: PIOCSTOP");
1306 return -1;
1307 }
Roland McGrath553a6092002-12-16 20:40:39 +00001308#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309#ifdef PIOCSET
1310 /* Set Run-on-Last-Close. */
1311 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001312 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 perror("PIOCSET PR_RLC");
1314 return -1;
1315 }
1316 /* Set or Reset Inherit-on-Fork. */
1317 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001318 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 perror("PIOC{SET,RESET} PR_FORK");
1320 return -1;
1321 }
1322#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001323#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1325 perror("PIOCSRLC");
1326 return -1;
1327 }
1328 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1329 perror("PIOC{S,R}FORK");
1330 return -1;
1331 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001332#else /* FREEBSD */
1333 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1334 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1335 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001336 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337 }
1338 arg &= ~PF_LINGER;
1339 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001340 perror("PIOCSFL");
1341 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001342 }
1343#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001345#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001346 /* Enable all syscall entries we care about. */
1347 premptyset(&syscalls);
1348 for (i = 1; i < MAX_QUALS; ++i) {
1349 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001350 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001351 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001352 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001353 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001354 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001355#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001356 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001357#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001358#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001359 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001360#endif
1361#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001362 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001363#endif
1364#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001365 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001366#endif
1367 }
1368 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369 perror("PIOCSENTRY");
1370 return -1;
1371 }
John Hughes19e49982001-10-19 08:59:12 +00001372 /* Enable the syscall exits. */
1373 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374 perror("PIOSEXIT");
1375 return -1;
1376 }
John Hughes19e49982001-10-19 08:59:12 +00001377 /* Enable signals we care about. */
1378 premptyset(&signals);
1379 for (i = 1; i < MAX_QUALS; ++i) {
1380 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001381 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001382 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 perror("PIOCSTRACE");
1385 return -1;
1386 }
John Hughes19e49982001-10-19 08:59:12 +00001387 /* Enable faults we care about */
1388 premptyset(&faults);
1389 for (i = 1; i < MAX_QUALS; ++i) {
1390 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001391 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001392 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001393 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001394 perror("PIOCSFAULT");
1395 return -1;
1396 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001397#else /* FREEBSD */
1398 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001399 arg = S_SIG | S_SCE | S_SCX;
1400 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001401 perror("PIOCBIS");
1402 return -1;
1403 }
1404#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001405 if (!attaching) {
1406#ifdef MIPS
1407 /*
1408 * The SGI PRSABORT doesn't work for pause() so
1409 * we send it a caught signal to wake it up.
1410 */
1411 kill(tcp->pid, SIGINT);
1412#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001413#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001415 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001416 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417 perror("PIOCRUN");
1418 return -1;
1419 }
Roland McGrath553a6092002-12-16 20:40:39 +00001420#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001421#endif /* !MIPS*/
1422#ifdef FREEBSD
1423 /* wake up the child if it received the SIGSTOP */
1424 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001425#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426 for (;;) {
1427 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001428 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001429 perror("PIOCWSTOP");
1430 return -1;
1431 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001432 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001433 tcp->flags &= ~TCB_INSYSCALL;
1434 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001435 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 break;
1437 }
1438 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001439#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001440 arg = 0;
1441 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001442#else /* FREEBSD */
1443 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001444#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 perror("PIOCRUN");
1446 return -1;
1447 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001448#ifdef FREEBSD
1449 /* handle the case where we "opened" the child before
1450 it did the kill -STOP */
1451 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1452 tcp->status.PR_WHAT == SIGSTOP)
1453 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001454#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001456#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001458#else /* FREEBSD */
1459 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001460 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001461 /* We are attaching to an already running process.
1462 * Try to figure out the state of the process in syscalls,
1463 * to handle the first event well.
1464 * This is done by having a look at the "wchan" property of the
1465 * process, which tells where it is stopped (if it is). */
1466 FILE * status;
1467 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001468
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001469 sprintf(proc, "/proc/%d/status", tcp->pid);
1470 status = fopen(proc, "r");
1471 if (status &&
1472 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1473 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1474 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1475 strcmp(wchan, "stopevent")) {
1476 /* The process is asleep in the middle of a syscall.
1477 Fake the syscall entry event */
1478 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1479 tcp->status.PR_WHY = PR_SYSENTRY;
1480 trace_syscall(tcp);
1481 }
1482 if (status)
1483 fclose(status);
1484 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001485 }
1486#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487#ifndef HAVE_POLLABLE_PROCFS
1488 if (proc_poll_pipe[0] != -1)
1489 proc_poller(tcp->pfd);
1490 else if (nprocs > 1) {
1491 proc_poll_open();
1492 proc_poller(last_pfd);
1493 proc_poller(tcp->pfd);
1494 }
1495 last_pfd = tcp->pfd;
1496#endif /* !HAVE_POLLABLE_PROCFS */
1497 return 0;
1498}
1499
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001500#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001502struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001503pid2tcb(int pid)
1504{
1505 int i;
1506
1507 if (pid <= 0)
1508 return NULL;
1509
1510 for (i = 0; i < tcbtabsize; i++) {
1511 struct tcb *tcp = tcbtab[i];
1512 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1513 return tcp;
1514 }
1515
1516 return NULL;
1517}
1518
1519#ifdef USE_PROCFS
1520
1521static struct tcb *
1522first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523{
1524 int i;
1525 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001526 for (i = 0; i < tcbtabsize; i++) {
1527 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528 if (tcp->flags & TCB_INUSE)
1529 return tcp;
1530 }
1531 return NULL;
1532}
1533
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001535pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536{
1537 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538
Roland McGrathca16be82003-01-10 19:55:28 +00001539 for (i = 0; i < tcbtabsize; i++) {
1540 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 if (tcp->pfd != pfd)
1542 continue;
1543 if (tcp->flags & TCB_INUSE)
1544 return tcp;
1545 }
1546 return NULL;
1547}
1548
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001549#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550
1551void
Denys Vlasenko12014262011-05-30 14:00:14 +02001552droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553{
1554 if (tcp->pid == 0)
1555 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001556#ifdef TCB_CLONE_THREAD
1557 if (tcp->nclone_threads > 0) {
1558 /* There are other threads left in this process, but this
1559 is the one whose PID represents the whole process.
1560 We need to keep this record around as a zombie until
1561 all the threads die. */
1562 tcp->flags |= TCB_EXITING;
1563 return;
1564 }
1565#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001567 if (debug)
1568 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001570
Roland McGrathe29341c2003-01-10 20:14:20 +00001571 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001572#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001573 if (tcp->flags & TCB_CLONE_THREAD)
1574 tcp->parent->nclone_threads--;
1575#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001576#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001577 /* Update fields like NCLONE_DETACHED, only
1578 for zombie group leader that has already reported
1579 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001580 function. The same condition as at the top of DETACH. */
1581 if ((tcp->flags & TCB_CLONE_THREAD) &&
1582 tcp->parent->nclone_threads == 0 &&
1583 (tcp->parent->flags & TCB_EXITING))
1584 droptcb(tcp->parent);
1585#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001586 tcp->parent = NULL;
1587 }
1588
1589 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590 if (tcp->pfd != -1) {
1591 close(tcp->pfd);
1592 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001593#ifdef FREEBSD
1594 if (tcp->pfd_reg != -1) {
1595 close(tcp->pfd_reg);
1596 tcp->pfd_reg = -1;
1597 }
1598 if (tcp->pfd_status != -1) {
1599 close(tcp->pfd_status);
1600 tcp->pfd_status = -1;
1601 }
Roland McGrath553a6092002-12-16 20:40:39 +00001602#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001603#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001604 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605#endif
1606 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001607
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001608 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001610
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001611 tcp->outf = 0;
1612}
1613
Roland McGrath0a463882007-07-05 18:43:16 +00001614/* detach traced process; continue with sig
1615 Never call DETACH twice on the same process as both unattached and
1616 attached-unstopped processes give the same ESRCH. For unattached process we
1617 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618
1619static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001620detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621{
1622 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001623#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001624 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001625 struct tcb *zombie = NULL;
1626
1627 /* If the group leader is lingering only because of this other
1628 thread now dying, then detach the leader as well. */
1629 if ((tcp->flags & TCB_CLONE_THREAD) &&
1630 tcp->parent->nclone_threads == 1 &&
1631 (tcp->parent->flags & TCB_EXITING))
1632 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001633#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634
1635 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001636 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637
1638#ifdef LINUX
1639 /*
1640 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001641 * before detaching. Arghh. We go through hoops
1642 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001644#if defined(SPARC)
1645#undef PTRACE_DETACH
1646#define PTRACE_DETACH PTRACE_SUNDETACH
1647#endif
Roland McGrath02203312007-06-11 22:06:31 +00001648 /*
1649 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1650 * expected SIGSTOP. We must catch exactly one as otherwise the
1651 * detached process would be left stopped (process state T).
1652 */
1653 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1655 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001656 }
1657 else if (errno != ESRCH) {
1658 /* Shouldn't happen. */
1659 perror("detach: ptrace(PTRACE_DETACH, ...)");
1660 }
Roland McGrath134813a2007-06-02 00:07:33 +00001661 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1662 : tcp->pid),
1663 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001664 if (errno != ESRCH)
1665 perror("detach: checking sanity");
1666 }
Roland McGrath02203312007-06-11 22:06:31 +00001667 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1668 ? tcp->parent->pid : tcp->pid),
1669 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001670 if (errno != ESRCH)
1671 perror("detach: stopping child");
1672 }
Roland McGrath02203312007-06-11 22:06:31 +00001673 else
1674 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001675 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001676 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001677#ifdef __WALL
1678 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1679 if (errno == ECHILD) /* Already gone. */
1680 break;
1681 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001682 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001683 break;
1684 }
1685#endif /* __WALL */
1686 /* No __WALL here. */
1687 if (waitpid(tcp->pid, &status, 0) < 0) {
1688 if (errno != ECHILD) {
1689 perror("detach: waiting");
1690 break;
1691 }
1692#ifdef __WCLONE
1693 /* If no processes, try clones. */
1694 if (wait4(tcp->pid, &status, __WCLONE,
1695 NULL) < 0) {
1696 if (errno != ECHILD)
1697 perror("detach: waiting");
1698 break;
1699 }
1700#endif /* __WCLONE */
1701 }
1702#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001703 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001704#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705 if (!WIFSTOPPED(status)) {
1706 /* Au revoir, mon ami. */
1707 break;
1708 }
1709 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001710 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 break;
1712 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001713 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001714 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001715 : WSTOPSIG(status));
1716 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001719 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001720#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721
1722#if defined(SUNOS4)
1723 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1724 if (sig && kill(tcp->pid, sig) < 0)
1725 perror("detach: kill");
1726 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001727 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001728#endif /* SUNOS4 */
1729
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 if (!qflag)
1731 fprintf(stderr, "Process %u detached\n", tcp->pid);
1732
1733 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001734
1735#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001736 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001737 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001738 droptcb(zombie);
1739 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001740#endif
1741
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742 return error;
1743}
1744
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001745#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001747static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748{
1749 int pid;
1750 int status;
1751
1752 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 }
1754}
1755
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001756#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757
1758static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001759cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760{
1761 int i;
1762 struct tcb *tcp;
1763
Roland McGrathee9d4352002-12-18 04:16:10 +00001764 for (i = 0; i < tcbtabsize; i++) {
1765 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766 if (!(tcp->flags & TCB_INUSE))
1767 continue;
1768 if (debug)
1769 fprintf(stderr,
1770 "cleanup: looking at pid %u\n", tcp->pid);
1771 if (tcp_last &&
1772 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001773 tprintf(" <unfinished ...>");
1774 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775 }
1776 if (tcp->flags & TCB_ATTACHED)
1777 detach(tcp, 0);
1778 else {
1779 kill(tcp->pid, SIGCONT);
1780 kill(tcp->pid, SIGTERM);
1781 }
1782 }
1783 if (cflag)
1784 call_summary(outf);
1785}
1786
1787static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001788interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789{
1790 interrupted = 1;
1791}
1792
1793#ifndef HAVE_STRERROR
1794
Roland McGrath6d2b3492002-12-30 00:51:30 +00001795#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796extern int sys_nerr;
1797extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001798#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001799
1800const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001801strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802{
1803 static char buf[64];
1804
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001805 if (err_no < 1 || err_no >= sys_nerr) {
1806 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807 return buf;
1808 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001809 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001810}
1811
1812#endif /* HAVE_STERRROR */
1813
1814#ifndef HAVE_STRSIGNAL
1815
Roland McGrath8f474e02003-01-14 07:53:33 +00001816#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001817extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001819#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1820extern char *_sys_siglist[];
1821#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822
1823const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001824strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825{
1826 static char buf[64];
1827
1828 if (sig < 1 || sig >= NSIG) {
1829 sprintf(buf, "Unknown signal %d", sig);
1830 return buf;
1831 }
1832#ifdef HAVE__SYS_SIGLIST
1833 return _sys_siglist[sig];
1834#else
1835 return sys_siglist[sig];
1836#endif
1837}
1838
1839#endif /* HAVE_STRSIGNAL */
1840
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001841#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001842
1843static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001844rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845{
1846 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847
Roland McGrathee9d4352002-12-18 04:16:10 +00001848 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001849 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001850 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001851 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001852 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001853 }
1854
Roland McGrathca16be82003-01-10 19:55:28 +00001855 for (i = j = 0; i < tcbtabsize; i++) {
1856 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857 if (!(tcp->flags & TCB_INUSE))
1858 continue;
1859 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001860 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861 j++;
1862 }
1863 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001864 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 }
1866}
1867
1868#ifndef HAVE_POLLABLE_PROCFS
1869
1870static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001871proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873 int i;
1874
1875 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001876 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877 }
1878 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001879 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 }
1881}
1882
1883static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001884proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001885{
1886 int i;
1887 int n;
1888 struct proc_pollfd pollinfo;
1889
1890 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1891 return n;
1892 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001893 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001894 }
1895 for (i = 0; i < nprocs; i++) {
1896 if (pollv[i].fd == pollinfo.fd)
1897 pollv[i].revents = pollinfo.revents;
1898 else
1899 pollv[i].revents = 0;
1900 }
1901 poller_pid = pollinfo.pid;
1902 return 1;
1903}
1904
1905static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001906wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907{
1908}
1909
1910static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001911proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912{
1913 struct proc_pollfd pollinfo;
1914 struct sigaction sa;
1915 sigset_t blocked_set, empty_set;
1916 int i;
1917 int n;
1918 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001919#ifdef FREEBSD
1920 struct procfs_status pfs;
1921#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922
1923 switch (fork()) {
1924 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001925 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926 case 0:
1927 break;
1928 default:
1929 return;
1930 }
1931
1932 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1933 sa.sa_flags = 0;
1934 sigemptyset(&sa.sa_mask);
1935 sigaction(SIGHUP, &sa, NULL);
1936 sigaction(SIGINT, &sa, NULL);
1937 sigaction(SIGQUIT, &sa, NULL);
1938 sigaction(SIGPIPE, &sa, NULL);
1939 sigaction(SIGTERM, &sa, NULL);
1940 sa.sa_handler = wakeup_handler;
1941 sigaction(SIGUSR1, &sa, NULL);
1942 sigemptyset(&blocked_set);
1943 sigaddset(&blocked_set, SIGUSR1);
1944 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1945 sigemptyset(&empty_set);
1946
1947 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001948 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001949 }
1950 n = rl.rlim_cur;
1951 for (i = 0; i < n; i++) {
1952 if (i != pfd && i != proc_poll_pipe[1])
1953 close(i);
1954 }
1955
1956 pollinfo.fd = pfd;
1957 pollinfo.pid = getpid();
1958 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001959#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001960 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1961#else
1962 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1963#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001964 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965 switch (errno) {
1966 case EINTR:
1967 continue;
1968 case EBADF:
1969 pollinfo.revents = POLLERR;
1970 break;
1971 case ENOENT:
1972 pollinfo.revents = POLLHUP;
1973 break;
1974 default:
1975 perror("proc_poller: PIOCWSTOP");
1976 }
1977 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1978 _exit(0);
1979 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001980 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1982 sigsuspend(&empty_set);
1983 }
1984}
1985
1986#endif /* !HAVE_POLLABLE_PROCFS */
1987
1988static int
1989choose_pfd()
1990{
1991 int i, j;
1992 struct tcb *tcp;
1993
1994 static int last;
1995
1996 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001997 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998 /*
1999 * The previous process is ready to run again. We'll
2000 * let it do so if it is currently in a syscall. This
2001 * heuristic improves the readability of the trace.
2002 */
2003 tcp = pfd2tcb(pollv[last].fd);
2004 if (tcp && (tcp->flags & TCB_INSYSCALL))
2005 return pollv[last].fd;
2006 }
2007
2008 for (i = 0; i < nprocs; i++) {
2009 /* Let competing children run round robin. */
2010 j = (i + last + 1) % nprocs;
2011 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2012 tcp = pfd2tcb(pollv[j].fd);
2013 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002014 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002015 }
2016 droptcb(tcp);
2017 return -1;
2018 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002019 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002020 last = j;
2021 return pollv[j].fd;
2022 }
2023 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002024 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025}
2026
2027static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002028trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002030#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002031 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002032#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033 struct tcb *tcp;
2034 int pfd;
2035 int what;
2036 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002037 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038
2039 for (;;) {
2040 if (interactive)
2041 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2042
2043 if (nprocs == 0)
2044 break;
2045
2046 switch (nprocs) {
2047 case 1:
2048#ifndef HAVE_POLLABLE_PROCFS
2049 if (proc_poll_pipe[0] == -1) {
2050#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002051 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052 if (!tcp)
2053 continue;
2054 pfd = tcp->pfd;
2055 if (pfd == -1)
2056 continue;
2057 break;
2058#ifndef HAVE_POLLABLE_PROCFS
2059 }
2060 /* fall through ... */
2061#endif /* !HAVE_POLLABLE_PROCFS */
2062 default:
2063#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002064#ifdef POLL_HACK
2065 /* On some systems (e.g. UnixWare) we get too much ugly
2066 "unfinished..." stuff when multiple proceses are in
2067 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002068
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002069 if (in_syscall) {
2070 struct pollfd pv;
2071 tcp = in_syscall;
2072 in_syscall = NULL;
2073 pv.fd = tcp->pfd;
2074 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002075 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002076 if (interrupted)
2077 return 0;
2078 continue;
2079 }
2080 else if (what == 1 && pv.revents & POLLWANT) {
2081 goto FOUND;
2082 }
2083 }
2084#endif
2085
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002086 if (poll(pollv, nprocs, INFTIM) < 0) {
2087 if (interrupted)
2088 return 0;
2089 continue;
2090 }
2091#else /* !HAVE_POLLABLE_PROCFS */
2092 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2093 if (interrupted)
2094 return 0;
2095 continue;
2096 }
2097#endif /* !HAVE_POLLABLE_PROCFS */
2098 pfd = choose_pfd();
2099 if (pfd == -1)
2100 continue;
2101 break;
2102 }
2103
2104 /* Look up `pfd' in our table. */
2105 if ((tcp = pfd2tcb(pfd)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002106 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 }
John Hughesb6643082002-05-23 11:02:22 +00002108#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002109 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002110#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002111 /* Get the status of the process. */
2112 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002113#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002114 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002115#else /* FREEBSD */
2116 /* Thanks to some scheduling mystery, the first poller
2117 sometimes waits for the already processed end of fork
2118 event. Doing a non blocking poll here solves the problem. */
2119 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002120 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002121 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002122 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002123#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002124 ioctl_errno = errno;
2125#ifndef HAVE_POLLABLE_PROCFS
2126 if (proc_poll_pipe[0] != -1) {
2127 if (ioctl_result < 0)
2128 kill(poller_pid, SIGKILL);
2129 else
2130 kill(poller_pid, SIGUSR1);
2131 }
2132#endif /* !HAVE_POLLABLE_PROCFS */
2133 }
2134 if (interrupted)
2135 return 0;
2136
2137 if (interactive)
2138 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2139
2140 if (ioctl_result < 0) {
2141 /* Find out what happened if it failed. */
2142 switch (ioctl_errno) {
2143 case EINTR:
2144 case EBADF:
2145 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002146#ifdef FREEBSD
2147 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002148#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 case ENOENT:
2150 droptcb(tcp);
2151 continue;
2152 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002153 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002154 }
2155 }
2156
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002157#ifdef FREEBSD
2158 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2159 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002160 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002161 continue;
2162 }
Roland McGrath553a6092002-12-16 20:40:39 +00002163#endif
2164
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002165 /* clear the just started flag */
2166 tcp->flags &= ~TCB_STARTUP;
2167
2168 /* set current output file */
2169 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002170 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171
2172 if (cflag) {
2173 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002174#ifdef FREEBSD
2175 char buf[1024];
2176 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002178 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2179 buf[len] = '\0';
2180 sscanf(buf,
2181 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2182 &stime.tv_sec, &stime.tv_usec);
2183 } else
2184 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002185#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2187 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002188#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2190 tcp->stime = stime;
2191 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002192 what = tcp->status.PR_WHAT;
2193 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002194#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002196 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2197 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002199 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002200 }
2201 }
2202 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002203#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002205#ifdef POLL_HACK
2206 in_syscall = tcp;
2207#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208 case PR_SYSEXIT:
2209 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002210 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 }
2212 break;
2213 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002214 if (cflag != CFLAG_ONLY_STATS
2215 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002216 printleader(tcp);
2217 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002218 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002219 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002220#ifdef PR_INFO
2221 if (tcp->status.PR_INFO.si_signo == what) {
2222 printleader(tcp);
2223 tprintf(" siginfo=");
2224 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002225 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002226 }
2227#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002228 }
2229 break;
2230 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002231 if (cflag != CFLAGS_ONLY_STATS
2232 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 printleader(tcp);
2234 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002235 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 }
2237 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002238#ifdef FREEBSD
2239 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002240 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002241#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002242 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002243 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002244 break;
2245 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002246 /* Remember current print column before continuing. */
2247 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002248 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002249#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002250 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002251#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002252 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002253#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002254 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002255 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 }
2257 }
2258 return 0;
2259}
2260
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002261#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002262
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002263#ifdef TCB_GROUP_EXITING
2264/* Handle an exit detach or death signal that is taking all the
2265 related clone threads with it. This is called in three circumstances:
2266 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2267 SIG == 0 Continuing TCP will perform an exit_group syscall.
2268 SIG == other Continuing TCP with SIG will kill the process.
2269*/
2270static int
2271handle_group_exit(struct tcb *tcp, int sig)
2272{
2273 /* We need to locate our records of all the clone threads
2274 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002275 struct tcb *leader = NULL;
2276
2277 if (tcp->flags & TCB_CLONE_THREAD)
2278 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002279
2280 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002281 if (leader != NULL && leader != tcp
2282 && !(leader->flags & TCB_GROUP_EXITING)
2283 && !(tcp->flags & TCB_STARTUP)
2284 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002285 fprintf(stderr,
2286 "PANIC: handle_group_exit: %d leader %d\n",
2287 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002288 }
2289 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002290 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002291 }
2292 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002293 /* Mark that we are taking the process down. */
2294 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002295 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002296 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002297 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002298 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002299 } else {
2300 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2301 cleanup();
2302 return -1;
2303 }
2304 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002305 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002306 if (leader != tcp)
2307 droptcb(tcp);
2308 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002309 /* The leader will report to us as parent now,
2310 and then we'll get to the SIG==-1 case. */
2311 return 0;
2312 }
2313 }
2314
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002315 return 0;
2316}
2317#endif
2318
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002319#ifdef LINUX
2320static int
2321handle_ptrace_event(int status, struct tcb *tcp)
2322{
2323 if (status >> 16 == PTRACE_EVENT_VFORK ||
2324 status >> 16 == PTRACE_EVENT_CLONE ||
2325 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002326 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002327
2328 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2329 if (errno != ESRCH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002330 error_msg_and_die("Cannot get new child's pid");
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002331 }
2332 return -1;
2333 }
2334 return handle_new_child(tcp, childpid, 0);
2335 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002336 if (status >> 16 == PTRACE_EVENT_EXEC) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002337 return 0;
2338 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002339 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2340 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002341 return 1;
2342}
2343#endif
2344
Roland McGratheb9e2e82009-06-02 16:49:22 -07002345static int
2346trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347{
2348 int pid;
2349 int wait_errno;
2350 int status;
2351 struct tcb *tcp;
2352#ifdef LINUX
2353 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002354#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002355 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002356#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002357#endif /* LINUX */
2358
Roland McGratheb9e2e82009-06-02 16:49:22 -07002359 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002360 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002361 return 0;
2362 if (interactive)
2363 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002364#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002365#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002366 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002367 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002368 /* this kernel does not support __WALL */
2369 wait4_options &= ~__WALL;
2370 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002371 pid = wait4(-1, &status, wait4_options,
2372 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002373 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002374 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002375 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002376 pid = wait4(-1, &status, __WCLONE,
2377 cflag ? &ru : NULL);
2378 if (pid == -1) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002379 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002380 }
2381 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002382#else
2383 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2384#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385#endif /* LINUX */
2386#ifdef SUNOS4
2387 pid = wait(&status);
2388#endif /* SUNOS4 */
2389 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002390 if (interactive)
2391 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002392
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002393 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002394 switch (wait_errno) {
2395 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002397 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398 /*
2399 * We would like to verify this case
2400 * but sometimes a race in Solbourne's
2401 * version of SunOS sometimes reports
2402 * ECHILD before sending us SIGCHILD.
2403 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002404 return 0;
2405 default:
2406 errno = wait_errno;
2407 perror("strace: wait");
2408 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002409 }
2410 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002411 if (pid == popen_pid) {
2412 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002413 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002414 continue;
2415 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002416 if (debug) {
2417 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2418#ifdef LINUX
2419 unsigned ev = (unsigned)status >> 16;
2420 if (ev) {
2421 static const char *const event_names[] = {
2422 [PTRACE_EVENT_CLONE] = "CLONE",
2423 [PTRACE_EVENT_FORK] = "FORK",
2424 [PTRACE_EVENT_VFORK] = "VFORK",
2425 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2426 [PTRACE_EVENT_EXEC] = "EXEC",
2427 [PTRACE_EVENT_EXIT] = "EXIT",
2428 };
2429 const char *e;
2430 if (ev < ARRAY_SIZE(event_names))
2431 e = event_names[ev];
2432 else {
2433 sprintf(buf, "?? (%u)", ev);
2434 e = buf;
2435 }
2436 fprintf(stderr, " PTRACE_EVENT_%s", e);
2437 }
2438#endif
2439 strcpy(buf, "???");
2440 if (WIFSIGNALED(status))
2441#ifdef WCOREDUMP
2442 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2443 WCOREDUMP(status) ? "core," : "",
2444 signame(WTERMSIG(status)));
2445#else
2446 sprintf(buf, "WIFSIGNALED,sig=%s",
2447 signame(WTERMSIG(status)));
2448#endif
2449 if (WIFEXITED(status))
2450 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2451 if (WIFSTOPPED(status))
2452 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
2453 if (WIFCONTINUED(status))
2454 strcpy(buf, "WIFCONTINUED");
2455 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2456 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002457
2458 /* Look up `pid' in our table. */
2459 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002460#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002461 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002462 /* This is needed to go with the CLONE_PTRACE
2463 changes in process.c/util.c: we might see
2464 the child's initial trap before we see the
2465 parent return from the clone syscall.
2466 Leave the child suspended until the parent
2467 returns from its system call. Only then
2468 will we have the association of parent and
2469 child so that we know how to do clearbpt
2470 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002471 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002472 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002473 if (!qflag)
2474 fprintf(stderr, "\
2475Process %d attached (waiting for parent)\n",
2476 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002477 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002478 else
2479 /* This can happen if a clone call used
2480 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002481#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002482 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002483 if (WIFSTOPPED(status))
2484 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002485 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002486 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002488 /* set current output file */
2489 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002490 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002491 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002492#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2494 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002495#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002496 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002497
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002498 if (tcp->flags & TCB_SUSPENDED) {
2499 /*
2500 * Apparently, doing any ptrace() call on a stopped
2501 * process, provokes the kernel to report the process
2502 * status again on a subsequent wait(), even if the
2503 * process has not been actually restarted.
2504 * Since we have inspected the arguments of suspended
2505 * processes we end up here testing for this case.
2506 */
2507 continue;
2508 }
2509 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002510 if (pid == strace_child)
2511 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002512 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2514 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002515 tprintf("+++ killed by %s %s+++",
2516 signame(WTERMSIG(status)),
2517#ifdef WCOREDUMP
2518 WCOREDUMP(status) ? "(core dumped) " :
2519#endif
2520 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002521 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002522 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002523#ifdef TCB_GROUP_EXITING
2524 handle_group_exit(tcp, -1);
2525#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002526 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002527#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002528 continue;
2529 }
2530 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002531 if (pid == strace_child)
2532 exit_code = WEXITSTATUS(status);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002533 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002534#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002535 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002536 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002537#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002538 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002539 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002540 "PANIC: attached pid %u exited with %d\n",
2541 pid, WEXITSTATUS(status));
2542 }
Roland McGrath0a396902003-06-10 03:05:53 +00002543 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002544 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002545 tprintf(" <unfinished ... exit status %d>\n",
2546 WEXITSTATUS(status));
2547 tcp_last = NULL;
2548 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002549#ifdef TCB_GROUP_EXITING
2550 handle_group_exit(tcp, -1);
2551#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002552 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002553#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002554 continue;
2555 }
2556 if (!WIFSTOPPED(status)) {
2557 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2558 droptcb(tcp);
2559 continue;
2560 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002561
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002562 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002563 if (handle_ptrace_event(status, tcp) != 1)
2564 goto tracing;
2565 }
2566
Roland McGrath02203312007-06-11 22:06:31 +00002567 /*
2568 * Interestingly, the process may stop
2569 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002570 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002571 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002572 * A no-MMU vforked child won't send up a signal,
2573 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002574 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002575 if ((tcp->flags & TCB_STARTUP) &&
2576 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 /*
2578 * This flag is there to keep us in sync.
2579 * Next time this process stops it should
2580 * really be entering a system call.
2581 */
2582 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002583 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002584 /*
2585 * One example is a breakpoint inherited from
2586 * parent through fork ().
2587 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002588 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2589 droptcb(tcp);
2590 cleanup();
2591 return -1;
2592 }
2593 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002594#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002595 /* If options were not set for this tracee yet */
2596 if (tcp->parent == NULL) {
2597 if (ptrace_setoptions) {
2598 if (debug)
2599 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2600 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2601 if (errno != ESRCH) {
2602 /* Should never happen, really */
2603 perror_msg_and_die("PTRACE_SETOPTIONS");
2604 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002605 }
2606 }
2607 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002608#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002609 goto tracing;
2610 }
2611
Denys Vlasenko75422762011-05-27 14:36:01 +02002612 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613 if (WSTOPSIG(status) == SIGSTOP &&
2614 (tcp->flags & TCB_SIGTRAPPED)) {
2615 /*
2616 * Trapped attempt to block SIGTRAP
2617 * Hope we are back in control now.
2618 */
2619 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002620 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002621 cleanup();
2622 return -1;
2623 }
2624 continue;
2625 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002626 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002628 siginfo_t si;
2629#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002630 long pc = 0;
2631 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002632
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002633 upeek(tcp, PT_CR_IPSR, &psr);
2634 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002635
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002636# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002637 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002638# define PC_FORMAT_STR " @ %lx"
2639# define PC_FORMAT_ARG pc
2640#else
2641# define PC_FORMAT_STR "%s"
2642# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002643#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002644 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002645 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2646 tprintf("--- ");
2647 printsiginfo(&si, verbose(tcp));
2648 tprintf(" (%s)" PC_FORMAT_STR " ---",
2649 strsignal(WSTOPSIG(status)),
2650 PC_FORMAT_ARG);
2651 } else
2652 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2653 strsignal(WSTOPSIG(status)),
2654 signame(WSTOPSIG(status)),
2655 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002656 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002657 }
Roland McGrath05690952004-10-20 01:00:27 +00002658 if (((tcp->flags & TCB_ATTACHED) ||
2659 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002660 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002661#ifdef TCB_GROUP_EXITING
2662 handle_group_exit(tcp, WSTOPSIG(status));
2663#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002664 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002665#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002666 continue;
2667 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002668 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002669 cleanup();
2670 return -1;
2671 }
2672 tcp->flags &= ~TCB_SUSPENDED;
2673 continue;
2674 }
Roland McGrath02203312007-06-11 22:06:31 +00002675 /* we handled the STATUS, we are permitted to interrupt now. */
2676 if (interrupted)
2677 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002678 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2679 /* ptrace() failed in trace_syscall() with ESRCH.
2680 * Likely a result of process disappearing mid-flight.
2681 * Observed case: exit_group() terminating
2682 * all processes in thread group. In this case, threads
2683 * "disappear" in an unpredictable moment without any
2684 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002685 */
2686 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002687 if (tcp_last) {
2688 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002689 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002690 */
2691 tcp_last->flags |= TCB_REPRINT;
2692 tprintf(" <unfinished ...>");
2693 printtrailer();
2694 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002695 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002696 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002697 ptrace(PTRACE_KILL,
2698 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699 droptcb(tcp);
2700 }
2701 continue;
2702 }
2703 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002704#ifdef TCB_GROUP_EXITING
2705 if (tcp->flags & TCB_GROUP_EXITING) {
2706 if (handle_group_exit(tcp, 0) < 0)
2707 return -1;
2708 continue;
2709 }
2710#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002711 if (tcp->flags & TCB_ATTACHED)
2712 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002713 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002714 cleanup();
2715 return -1;
2716 }
2717 continue;
2718 }
2719 if (tcp->flags & TCB_SUSPENDED) {
2720 if (!qflag)
2721 fprintf(stderr, "Process %u suspended\n", pid);
2722 continue;
2723 }
2724 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002725 /* Remember current print column before continuing. */
2726 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002727 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002728 cleanup();
2729 return -1;
2730 }
2731 }
2732 return 0;
2733}
2734
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002735#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002736
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002737#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002738
2739void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002740tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002741{
2742 va_list args;
2743
Andreas Schwabe5355de2009-10-27 16:56:43 +01002744 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002745 if (outf) {
2746 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002747 if (n < 0) {
2748 if (outf != stderr)
2749 perror(outfname == NULL
2750 ? "<writing to pipe>" : outfname);
2751 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002752 curcol += n;
2753 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002754 va_end(args);
2755 return;
2756}
2757
2758void
Denys Vlasenko12014262011-05-30 14:00:14 +02002759printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002760{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002761 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002762 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002763 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002764 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002765 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002766 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002767 tprintf("= ? <unavailable>\n");
2768 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002769 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002770 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002771 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002772 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002773 }
2774 curcol = 0;
2775 if ((followfork == 1 || pflag_seen > 1) && outfname)
2776 tprintf("%-5d ", tcp->pid);
2777 else if (nprocs > 1 && !outfname)
2778 tprintf("[pid %5u] ", tcp->pid);
2779 if (tflag) {
2780 char str[sizeof("HH:MM:SS")];
2781 struct timeval tv, dtv;
2782 static struct timeval otv;
2783
2784 gettimeofday(&tv, NULL);
2785 if (rflag) {
2786 if (otv.tv_sec == 0)
2787 otv = tv;
2788 tv_sub(&dtv, &tv, &otv);
2789 tprintf("%6ld.%06ld ",
2790 (long) dtv.tv_sec, (long) dtv.tv_usec);
2791 otv = tv;
2792 }
2793 else if (tflag > 2) {
2794 tprintf("%ld.%06ld ",
2795 (long) tv.tv_sec, (long) tv.tv_usec);
2796 }
2797 else {
2798 time_t local = tv.tv_sec;
2799 strftime(str, sizeof(str), "%T", localtime(&local));
2800 if (tflag > 1)
2801 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2802 else
2803 tprintf("%s ", str);
2804 }
2805 }
2806 if (iflag)
2807 printcall(tcp);
2808}
2809
2810void
Denys Vlasenko12014262011-05-30 14:00:14 +02002811tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002812{
2813 if (curcol < col)
2814 tprintf("%*s", col - curcol, "");
2815}
2816
2817void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002818printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002819{
2820 tprintf("\n");
2821 tcp_last = NULL;
2822}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002823
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002824#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002825
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002826int
2827mp_ioctl(int fd, int cmd, void *arg, int size)
2828{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002829 struct iovec iov[2];
2830 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002831
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002832 iov[0].iov_base = &cmd;
2833 iov[0].iov_len = sizeof cmd;
2834 if (arg) {
2835 ++n;
2836 iov[1].iov_base = arg;
2837 iov[1].iov_len = size;
2838 }
Roland McGrath553a6092002-12-16 20:40:39 +00002839
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002840 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002841}
2842
2843#endif