blob: c3fd94838e1ee910b688c6e0edc353b849e9783d [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);
Roland McGrath02203312007-06-11 22:06:31 +0000520 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000521
522 if (daemonized_tracer) {
523 /*
524 * It is our grandparent we trace, not a -p PID.
525 * Don't want to just detach on exit, so...
526 */
527 tcp->flags &= ~TCB_ATTACHED;
528 /*
529 * Make parent go away.
530 * Also makes grandparent's wait() unblock.
531 */
532 kill(getppid(), SIGKILL);
533 }
534
Roland McGrath02203312007-06-11 22:06:31 +0000535#endif /* !USE_PROCFS */
536 if (!qflag)
537 fprintf(stderr,
538 "Process %u attached - interrupt to quit\n",
539 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200540 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000541
542 if (interactive)
543 sigprocmask(SIG_SETMASK, &empty_set, NULL);
544}
545
546static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200547startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000548{
549 struct stat statbuf;
550 const char *filename;
551 char pathname[MAXPATHLEN];
552 int pid = 0;
553 struct tcb *tcp;
554
555 filename = argv[0];
556 if (strchr(filename, '/')) {
557 if (strlen(filename) > sizeof pathname - 1) {
558 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200559 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000560 }
561 strcpy(pathname, filename);
562 }
563#ifdef USE_DEBUGGING_EXEC
564 /*
565 * Debuggers customarily check the current directory
566 * first regardless of the path but doing that gives
567 * security geeks a panic attack.
568 */
569 else if (stat(filename, &statbuf) == 0)
570 strcpy(pathname, filename);
571#endif /* USE_DEBUGGING_EXEC */
572 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000573 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000574 int m, n, len;
575
576 for (path = getenv("PATH"); path && *path; path += m) {
577 if (strchr(path, ':')) {
578 n = strchr(path, ':') - path;
579 m = n + 1;
580 }
581 else
582 m = n = strlen(path);
583 if (n == 0) {
584 if (!getcwd(pathname, MAXPATHLEN))
585 continue;
586 len = strlen(pathname);
587 }
588 else if (n > sizeof pathname - 1)
589 continue;
590 else {
591 strncpy(pathname, path, n);
592 len = n;
593 }
594 if (len && pathname[len - 1] != '/')
595 pathname[len++] = '/';
596 strcpy(pathname + len, filename);
597 if (stat(pathname, &statbuf) == 0 &&
598 /* Accept only regular files
599 with some execute bits set.
600 XXX not perfect, might still fail */
601 S_ISREG(statbuf.st_mode) &&
602 (statbuf.st_mode & 0111))
603 break;
604 }
605 }
606 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200607 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000608 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000609 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000610 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200611 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000612 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200613 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
614 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000615 ) {
616 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000617#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200618 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000619#ifdef MIPS
620 /* Kludge for SGI, see proc_open for details. */
621 sa.sa_handler = foobar;
622 sa.sa_flags = 0;
623 sigemptyset(&sa.sa_mask);
624 sigaction(SIGINT, &sa, NULL);
625#endif /* MIPS */
626#ifndef FREEBSD
627 pause();
628#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000629 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000630#endif /* FREEBSD */
631#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200632 if (outf != stderr)
633 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000634
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000635 if (!daemonized_tracer) {
636 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200637 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000638 }
639 if (debug)
640 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000641 }
Roland McGrath02203312007-06-11 22:06:31 +0000642
643 if (username != NULL || geteuid() == 0) {
644 uid_t run_euid = run_uid;
645 gid_t run_egid = run_gid;
646
647 if (statbuf.st_mode & S_ISUID)
648 run_euid = statbuf.st_uid;
649 if (statbuf.st_mode & S_ISGID)
650 run_egid = statbuf.st_gid;
651
652 /*
653 * It is important to set groups before we
654 * lose privileges on setuid.
655 */
656 if (username != NULL) {
657 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200658 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000659 }
660 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200661 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000662 }
663 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200664 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000665 }
666 }
667 }
668 else
669 setreuid(run_uid, run_uid);
670
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000671 if (!daemonized_tracer) {
672 /*
673 * Induce an immediate stop so that the parent
674 * will resume us with PTRACE_SYSCALL and display
675 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400676 * Unless of course we're on a no-MMU system where
677 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000678 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400679 if (!strace_vforked)
680 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000681 } else {
682 struct sigaction sv_sigchld;
683 sigaction(SIGCHLD, NULL, &sv_sigchld);
684 /*
685 * Make sure it is not SIG_IGN, otherwise wait
686 * will not block.
687 */
688 signal(SIGCHLD, SIG_DFL);
689 /*
690 * Wait for grandchild to attach to us.
691 * It kills child after that, and wait() unblocks.
692 */
693 alarm(3);
694 wait(NULL);
695 alarm(0);
696 sigaction(SIGCHLD, &sv_sigchld, NULL);
697 }
Roland McGrath02203312007-06-11 22:06:31 +0000698#endif /* !USE_PROCFS */
699
700 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200701 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000702 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000703
704 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200705 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
706 strace_tracer_pid = getpid();
707
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000709 if (daemonized_tracer) {
710 /* We want subsequent startup_attach() to attach to it. */
711 tcp->flags |= TCB_ATTACHED;
712 }
Roland McGrath02203312007-06-11 22:06:31 +0000713#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200715 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000716 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000717#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000718}
719
Wang Chaob13c0de2010-11-12 17:25:19 +0800720#ifdef LINUX
721/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000722 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800723 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000724 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800725 */
726static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200727test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800728{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000729 int pid, expected_grandchild = 0, found_grandchild = 0;
730 const unsigned int test_options = PTRACE_O_TRACECLONE |
731 PTRACE_O_TRACEFORK |
732 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800733
734 if ((pid = fork()) < 0)
735 return -1;
736 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000737 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800738 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800739 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000740 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800741 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000742
743 while (1) {
744 int status, tracee_pid;
745
746 tracee_pid = wait(&status);
747 if (tracee_pid == -1) {
748 if (errno == EINTR)
749 continue;
750 else if (errno == ECHILD)
751 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200752 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000753 return -1;
754 }
755 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000756 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000757 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
758 errno != ESRCH)
759 kill(tracee_pid, SIGKILL);
760 }
761 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000762 switch (WSTOPSIG(status)) {
763 case SIGSTOP:
764 if (ptrace(PTRACE_SETOPTIONS, pid,
765 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000766 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800767 return -1;
768 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000769 break;
770 case SIGTRAP:
771 if (status >> 16 == PTRACE_EVENT_FORK) {
772 long msg = 0;
773
774 if (ptrace(PTRACE_GETEVENTMSG, pid,
775 NULL, (long) &msg) == 0)
776 expected_grandchild = msg;
777 }
778 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800779 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000780 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
781 errno != ESRCH)
782 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800783 }
784 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000785 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200786 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800787 return 0;
788}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200789
790/*
791 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
792 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
793 * and then see whether it will stop with (SIGTRAP | 0x80).
794 *
795 * Use of this option enables correct handling of user-generated SIGTRAPs,
796 * and SIGTRAPs generated by special instructions such as int3 on x86:
797 * _start: .globl _start
798 * int3
799 * movl $42, %ebx
800 * movl $1, %eax
801 * int $0x80
802 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
803 */
804static void
805test_ptrace_setoptions_for_all(void)
806{
807 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
808 int pid;
809 int it_worked = 0;
810
811 pid = fork();
812 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200813 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200814
815 if (pid == 0) {
816 pid = getpid();
817 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200818 /* Note: exits with exitcode 1 */
819 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200820 kill(pid, SIGSTOP);
821 _exit(0); /* parent should see entry into this syscall */
822 }
823
824 while (1) {
825 int status, tracee_pid;
826
827 errno = 0;
828 tracee_pid = wait(&status);
829 if (tracee_pid <= 0) {
830 if (errno == EINTR)
831 continue;
832 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200833 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200834 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200835 if (WIFEXITED(status)) {
836 if (WEXITSTATUS(status) == 0)
837 break;
838 /* PTRACE_TRACEME failed in child. This is fatal. */
839 exit(1);
840 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200841 if (!WIFSTOPPED(status)) {
842 kill(pid, SIGKILL);
843 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
844 }
845 if (WSTOPSIG(status) == SIGSTOP) {
846 /*
847 * We don't check "options aren't accepted" error.
848 * If it happens, we'll never get (SIGTRAP | 0x80),
849 * and thus will decide to not use the option.
850 * IOW: the outcome of the test will be correct.
851 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200852 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
853 if (errno != EINVAL)
854 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200855 }
856 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
857 it_worked = 1;
858 }
859 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
860 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200861 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200862 }
863 }
864
865 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200866 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200867 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200868 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200869 fprintf(stderr, "ptrace_setoptions = %#x\n",
870 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200871 return;
872 }
873
874 fprintf(stderr,
875 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
876}
Wang Chaob13c0de2010-11-12 17:25:19 +0800877#endif
878
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000880main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 struct tcb *tcp;
883 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000884 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885 struct sigaction sa;
886
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000887 progname = argv[0] ? argv[0] : "strace";
888
Denys Vlasenko75422762011-05-27 14:36:01 +0200889 strace_tracer_pid = getpid();
890
Roland McGrathee9d4352002-12-18 04:16:10 +0000891 /* Allocate the initial tcbtab. */
892 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200893 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200894 if (tcbtab == NULL)
895 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200896 tcp = calloc(tcbtabsize, sizeof(*tcp));
897 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200898 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200899 for (c = 0; c < tcbtabsize; c++)
900 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000901
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902 outf = stderr;
903 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000904 set_sortby(DEFAULT_SORTBY);
905 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906 qualify("trace=all");
907 qualify("abbrev=all");
908 qualify("verbose=all");
909 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000911 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000912#ifndef USE_PROCFS
913 "D"
914#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000915 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 switch (c) {
917 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000918 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200919 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000920 }
921 cflag = CFLAG_ONLY_STATS;
922 break;
923 case 'C':
924 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200925 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000926 }
927 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 break;
929 case 'd':
930 debug++;
931 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000932#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000933 case 'D':
934 daemonized_tracer = 1;
935 break;
936#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000937 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000938 optF = 1;
939 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 case 'f':
941 followfork++;
942 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000943 case 'h':
944 usage(stdout, 0);
945 break;
946 case 'i':
947 iflag++;
948 break;
949 case 'q':
950 qflag++;
951 break;
952 case 'r':
953 rflag++;
954 tflag++;
955 break;
956 case 't':
957 tflag++;
958 break;
959 case 'T':
960 dtime++;
961 break;
962 case 'x':
963 xflag++;
964 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000965 case 'y':
966 show_fd_path = 1;
967 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 case 'v':
969 qualify("abbrev=none");
970 break;
971 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000972 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 exit(0);
974 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000975 case 'z':
976 not_failing_only = 1;
977 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 case 'a':
979 acolumn = atoi(optarg);
980 break;
981 case 'e':
982 qualify(optarg);
983 break;
984 case 'o':
985 outfname = strdup(optarg);
986 break;
987 case 'O':
988 set_overhead(atoi(optarg));
989 break;
990 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +0000991 if ((pid = atoi(optarg)) <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200992 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993 break;
994 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200995 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200996 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997 break;
998 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000999 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 tcp->flags |= TCB_ATTACHED;
1001 pflag_seen++;
1002 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001003 case 'P':
1004 tracing_paths = 1;
1005 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001006 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001007 }
1008 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 case 's':
1010 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001011 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001012 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001013 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 break;
1015 case 'S':
1016 set_sortby(optarg);
1017 break;
1018 case 'u':
1019 username = strdup(optarg);
1020 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001021 case 'E':
1022 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001023 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001024 }
1025 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 default:
1027 usage(stderr, 1);
1028 break;
1029 }
1030 }
1031
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001032 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001033 usage(stderr, 1);
1034
Wang Chaod322a4b2010-08-05 14:30:11 +08001035 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001036 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001037 }
1038
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001039 if (!followfork)
1040 followfork = optF;
1041
Roland McGrathcb9def62006-04-25 07:48:03 +00001042 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001043 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001044 }
1045
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 /* See if they want to run as another user. */
1047 if (username != NULL) {
1048 struct passwd *pent;
1049
1050 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001051 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 }
1053 if ((pent = getpwnam(username)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001054 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 }
1056 run_uid = pent->pw_uid;
1057 run_gid = pent->pw_gid;
1058 }
1059 else {
1060 run_uid = getuid();
1061 run_gid = getgid();
1062 }
1063
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001064#ifdef LINUX
1065 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001066 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001067 fprintf(stderr,
1068 "Test for options supported by PTRACE_SETOPTIONS "
1069 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001070 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001071 }
1072 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001073 fprintf(stderr, "ptrace_setoptions = %#x\n",
1074 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001075 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001076 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001077#endif
1078
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 /* Check if they want to redirect the output. */
1080 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001081 /* See if they want to pipe the output. */
1082 if (outfname[0] == '|' || outfname[0] == '!') {
1083 /*
1084 * We can't do the <outfname>.PID funny business
1085 * when using popen, so prohibit it.
1086 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001087 if (followfork > 1)
1088 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1089 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001090 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001091 else if (followfork <= 1)
1092 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093 }
1094
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001095 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1096 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001097 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001098 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001099 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001102 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001103
Roland McGrath54cc1c82007-11-03 23:34:11 +00001104 /* Valid states here:
1105 optind < argc pflag_seen outfname interactive
1106 1 0 0 1
1107 0 1 0 1
1108 1 0 1 0
1109 0 1 1 1
1110 */
1111
1112 /* STARTUP_CHILD must be called before the signal handlers get
1113 installed below as they are inherited into the spawned process.
1114 Also we do not need to be protected by them as during interruption
1115 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1116 if (!pflag_seen)
1117 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 sigemptyset(&empty_set);
1120 sigemptyset(&blocked_set);
1121 sa.sa_handler = SIG_IGN;
1122 sigemptyset(&sa.sa_mask);
1123 sa.sa_flags = 0;
1124 sigaction(SIGTTOU, &sa, NULL);
1125 sigaction(SIGTTIN, &sa, NULL);
1126 if (interactive) {
1127 sigaddset(&blocked_set, SIGHUP);
1128 sigaddset(&blocked_set, SIGINT);
1129 sigaddset(&blocked_set, SIGQUIT);
1130 sigaddset(&blocked_set, SIGPIPE);
1131 sigaddset(&blocked_set, SIGTERM);
1132 sa.sa_handler = interrupt;
1133#ifdef SUNOS4
1134 /* POSIX signals on sunos4.1 are a little broken. */
1135 sa.sa_flags = SA_INTERRUPT;
1136#endif /* SUNOS4 */
1137 }
1138 sigaction(SIGHUP, &sa, NULL);
1139 sigaction(SIGINT, &sa, NULL);
1140 sigaction(SIGQUIT, &sa, NULL);
1141 sigaction(SIGPIPE, &sa, NULL);
1142 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001143#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 sa.sa_handler = reaper;
1145 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001146#else
1147 /* Make sure SIGCHLD has the default action so that waitpid
1148 definitely works without losing track of children. The user
1149 should not have given us a bogus state to inherit, but he might
1150 have. Arguably we should detect SIG_IGN here and pass it on
1151 to children, but probably noone really needs that. */
1152 sa.sa_handler = SIG_DFL;
1153 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001154#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001156 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001157 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001158
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 if (trace() < 0)
1160 exit(1);
1161 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001162 fflush(NULL);
1163 if (exit_code > 0xff) {
1164 /* Child was killed by a signal, mimic that. */
1165 exit_code &= 0xff;
1166 signal(exit_code, SIG_DFL);
1167 raise(exit_code);
1168 /* Paranoia - what if this signal is not fatal?
1169 Exit with 128 + signo then. */
1170 exit_code += 128;
1171 }
1172 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173}
1174
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001175static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001176expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001177{
1178 /* Allocate some more TCBs and expand the table.
1179 We don't want to relocate the TCBs because our
1180 callers have pointers and it would be a pain.
1181 So tcbtab is a table of pointers. Since we never
1182 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001183 int i = tcbtabsize;
1184 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1185 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1186 if (newtab == NULL || newtcbs == NULL)
1187 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001188 tcbtabsize *= 2;
1189 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001190 while (i < tcbtabsize)
1191 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001192}
1193
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001195alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196{
1197 int i;
1198 struct tcb *tcp;
1199
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001200 if (nprocs == tcbtabsize)
1201 expand_tcbtab();
1202
Roland McGrathee9d4352002-12-18 04:16:10 +00001203 for (i = 0; i < tcbtabsize; i++) {
1204 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001206 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 tcp->flags = TCB_INUSE | TCB_STARTUP;
1209 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 tcp->pfd = -1;
1211 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001212 if (debug)
1213 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001214 if (command_options_parsed)
1215 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 return tcp;
1217 }
1218 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001219 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220}
1221
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001222#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001224proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001225{
1226 char proc[32];
1227 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001228#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001229 int i;
1230 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 sigset_t signals;
1232 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001233#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234#ifndef HAVE_POLLABLE_PROCFS
1235 static int last_pfd;
1236#endif
1237
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001238#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001239 /* Open the process pseudo-files in /proc. */
1240 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1241 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 perror("strace: open(\"/proc/...\", ...)");
1243 return -1;
1244 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001245 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001246 sprintf(proc, "/proc/%d/status", tcp->pid);
1247 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1248 perror("strace: open(\"/proc/...\", ...)");
1249 return -1;
1250 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001251 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001252 sprintf(proc, "/proc/%d/as", tcp->pid);
1253 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1254 perror("strace: open(\"/proc/...\", ...)");
1255 return -1;
1256 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001257 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001258#else
1259 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001260#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001261 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001262 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001263#else /* FREEBSD */
1264 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001265 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001266#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001267 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001268 perror("strace: open(\"/proc/...\", ...)");
1269 return -1;
1270 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001271 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001272#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273#ifdef FREEBSD
1274 sprintf(proc, "/proc/%d/regs", tcp->pid);
1275 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1276 perror("strace: open(\"/proc/.../regs\", ...)");
1277 return -1;
1278 }
1279 if (cflag) {
1280 sprintf(proc, "/proc/%d/status", tcp->pid);
1281 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1282 perror("strace: open(\"/proc/.../status\", ...)");
1283 return -1;
1284 }
1285 } else
1286 tcp->pfd_status = -1;
1287#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001288 rebuild_pollv();
1289 if (!attaching) {
1290 /*
1291 * Wait for the child to pause. Because of a race
1292 * condition we have to poll for the event.
1293 */
1294 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001295 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001296 perror("strace: PIOCSTATUS");
1297 return -1;
1298 }
1299 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001300 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001301 }
1302 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001303#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001304 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001305 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001306 perror("strace: PIOCSTOP");
1307 return -1;
1308 }
Roland McGrath553a6092002-12-16 20:40:39 +00001309#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310#ifdef PIOCSET
1311 /* Set Run-on-Last-Close. */
1312 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001313 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 perror("PIOCSET PR_RLC");
1315 return -1;
1316 }
1317 /* Set or Reset Inherit-on-Fork. */
1318 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001319 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 perror("PIOC{SET,RESET} PR_FORK");
1321 return -1;
1322 }
1323#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001324#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1326 perror("PIOCSRLC");
1327 return -1;
1328 }
1329 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1330 perror("PIOC{S,R}FORK");
1331 return -1;
1332 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001333#else /* FREEBSD */
1334 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1335 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1336 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001337 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338 }
1339 arg &= ~PF_LINGER;
1340 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001341 perror("PIOCSFL");
1342 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001343 }
1344#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001346#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001347 /* Enable all syscall entries we care about. */
1348 premptyset(&syscalls);
1349 for (i = 1; i < MAX_QUALS; ++i) {
1350 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001351 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001352 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001353 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001354 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001355 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001356#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001357 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001358#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001359#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001360 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001361#endif
1362#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001363 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001364#endif
1365#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001366 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001367#endif
1368 }
1369 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001370 perror("PIOCSENTRY");
1371 return -1;
1372 }
John Hughes19e49982001-10-19 08:59:12 +00001373 /* Enable the syscall exits. */
1374 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375 perror("PIOSEXIT");
1376 return -1;
1377 }
John Hughes19e49982001-10-19 08:59:12 +00001378 /* Enable signals we care about. */
1379 premptyset(&signals);
1380 for (i = 1; i < MAX_QUALS; ++i) {
1381 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001382 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001383 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001384 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385 perror("PIOCSTRACE");
1386 return -1;
1387 }
John Hughes19e49982001-10-19 08:59:12 +00001388 /* Enable faults we care about */
1389 premptyset(&faults);
1390 for (i = 1; i < MAX_QUALS; ++i) {
1391 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001392 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001393 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001394 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395 perror("PIOCSFAULT");
1396 return -1;
1397 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001398#else /* FREEBSD */
1399 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001400 arg = S_SIG | S_SCE | S_SCX;
1401 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001402 perror("PIOCBIS");
1403 return -1;
1404 }
1405#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 if (!attaching) {
1407#ifdef MIPS
1408 /*
1409 * The SGI PRSABORT doesn't work for pause() so
1410 * we send it a caught signal to wake it up.
1411 */
1412 kill(tcp->pid, SIGINT);
1413#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001414#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001416 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001417 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418 perror("PIOCRUN");
1419 return -1;
1420 }
Roland McGrath553a6092002-12-16 20:40:39 +00001421#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001422#endif /* !MIPS*/
1423#ifdef FREEBSD
1424 /* wake up the child if it received the SIGSTOP */
1425 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001426#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427 for (;;) {
1428 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001429 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430 perror("PIOCWSTOP");
1431 return -1;
1432 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001433 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001434 tcp->flags &= ~TCB_INSYSCALL;
1435 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001436 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437 break;
1438 }
1439 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001440#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001441 arg = 0;
1442 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001443#else /* FREEBSD */
1444 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001445#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446 perror("PIOCRUN");
1447 return -1;
1448 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001449#ifdef FREEBSD
1450 /* handle the case where we "opened" the child before
1451 it did the kill -STOP */
1452 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1453 tcp->status.PR_WHAT == SIGSTOP)
1454 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001455#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001457#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001459#else /* FREEBSD */
1460 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001461 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001462 /* We are attaching to an already running process.
1463 * Try to figure out the state of the process in syscalls,
1464 * to handle the first event well.
1465 * This is done by having a look at the "wchan" property of the
1466 * process, which tells where it is stopped (if it is). */
1467 FILE * status;
1468 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001469
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001470 sprintf(proc, "/proc/%d/status", tcp->pid);
1471 status = fopen(proc, "r");
1472 if (status &&
1473 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1474 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1475 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1476 strcmp(wchan, "stopevent")) {
1477 /* The process is asleep in the middle of a syscall.
1478 Fake the syscall entry event */
1479 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1480 tcp->status.PR_WHY = PR_SYSENTRY;
1481 trace_syscall(tcp);
1482 }
1483 if (status)
1484 fclose(status);
1485 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001486 }
1487#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488#ifndef HAVE_POLLABLE_PROCFS
1489 if (proc_poll_pipe[0] != -1)
1490 proc_poller(tcp->pfd);
1491 else if (nprocs > 1) {
1492 proc_poll_open();
1493 proc_poller(last_pfd);
1494 proc_poller(tcp->pfd);
1495 }
1496 last_pfd = tcp->pfd;
1497#endif /* !HAVE_POLLABLE_PROCFS */
1498 return 0;
1499}
1500
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001501#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001503struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001504pid2tcb(int pid)
1505{
1506 int i;
1507
1508 if (pid <= 0)
1509 return NULL;
1510
1511 for (i = 0; i < tcbtabsize; i++) {
1512 struct tcb *tcp = tcbtab[i];
1513 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1514 return tcp;
1515 }
1516
1517 return NULL;
1518}
1519
1520#ifdef USE_PROCFS
1521
1522static struct tcb *
1523first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001524{
1525 int i;
1526 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001527 for (i = 0; i < tcbtabsize; i++) {
1528 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 if (tcp->flags & TCB_INUSE)
1530 return tcp;
1531 }
1532 return NULL;
1533}
1534
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001536pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537{
1538 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539
Roland McGrathca16be82003-01-10 19:55:28 +00001540 for (i = 0; i < tcbtabsize; i++) {
1541 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542 if (tcp->pfd != pfd)
1543 continue;
1544 if (tcp->flags & TCB_INUSE)
1545 return tcp;
1546 }
1547 return NULL;
1548}
1549
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001550#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551
1552void
Denys Vlasenko12014262011-05-30 14:00:14 +02001553droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554{
1555 if (tcp->pid == 0)
1556 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001557#ifdef TCB_CLONE_THREAD
1558 if (tcp->nclone_threads > 0) {
1559 /* There are other threads left in this process, but this
1560 is the one whose PID represents the whole process.
1561 We need to keep this record around as a zombie until
1562 all the threads die. */
1563 tcp->flags |= TCB_EXITING;
1564 return;
1565 }
1566#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001568 if (debug)
1569 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001571
Roland McGrathe29341c2003-01-10 20:14:20 +00001572 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001573#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001574 if (tcp->flags & TCB_CLONE_THREAD)
1575 tcp->parent->nclone_threads--;
1576#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001577#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001578 /* Update fields like NCLONE_DETACHED, only
1579 for zombie group leader that has already reported
1580 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001581 function. The same condition as at the top of DETACH. */
1582 if ((tcp->flags & TCB_CLONE_THREAD) &&
1583 tcp->parent->nclone_threads == 0 &&
1584 (tcp->parent->flags & TCB_EXITING))
1585 droptcb(tcp->parent);
1586#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001587 tcp->parent = NULL;
1588 }
1589
1590 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001591 if (tcp->pfd != -1) {
1592 close(tcp->pfd);
1593 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001594#ifdef FREEBSD
1595 if (tcp->pfd_reg != -1) {
1596 close(tcp->pfd_reg);
1597 tcp->pfd_reg = -1;
1598 }
1599 if (tcp->pfd_status != -1) {
1600 close(tcp->pfd_status);
1601 tcp->pfd_status = -1;
1602 }
Roland McGrath553a6092002-12-16 20:40:39 +00001603#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001604#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001605 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606#endif
1607 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001608
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001609 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001611
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612 tcp->outf = 0;
1613}
1614
Roland McGrath0a463882007-07-05 18:43:16 +00001615/* detach traced process; continue with sig
1616 Never call DETACH twice on the same process as both unattached and
1617 attached-unstopped processes give the same ESRCH. For unattached process we
1618 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619
1620static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001621detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622{
1623 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001624#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001625 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001626 struct tcb *zombie = NULL;
1627
1628 /* If the group leader is lingering only because of this other
1629 thread now dying, then detach the leader as well. */
1630 if ((tcp->flags & TCB_CLONE_THREAD) &&
1631 tcp->parent->nclone_threads == 1 &&
1632 (tcp->parent->flags & TCB_EXITING))
1633 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001634#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635
1636 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001637 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638
1639#ifdef LINUX
1640 /*
1641 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001642 * before detaching. Arghh. We go through hoops
1643 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001645#if defined(SPARC)
1646#undef PTRACE_DETACH
1647#define PTRACE_DETACH PTRACE_SUNDETACH
1648#endif
Roland McGrath02203312007-06-11 22:06:31 +00001649 /*
1650 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1651 * expected SIGSTOP. We must catch exactly one as otherwise the
1652 * detached process would be left stopped (process state T).
1653 */
1654 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1656 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001657 }
1658 else if (errno != ESRCH) {
1659 /* Shouldn't happen. */
1660 perror("detach: ptrace(PTRACE_DETACH, ...)");
1661 }
Roland McGrath134813a2007-06-02 00:07:33 +00001662 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1663 : tcp->pid),
1664 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001665 if (errno != ESRCH)
1666 perror("detach: checking sanity");
1667 }
Roland McGrath02203312007-06-11 22:06:31 +00001668 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1669 ? tcp->parent->pid : tcp->pid),
1670 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001671 if (errno != ESRCH)
1672 perror("detach: stopping child");
1673 }
Roland McGrath02203312007-06-11 22:06:31 +00001674 else
1675 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001676 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001678#ifdef __WALL
1679 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1680 if (errno == ECHILD) /* Already gone. */
1681 break;
1682 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001683 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001684 break;
1685 }
1686#endif /* __WALL */
1687 /* No __WALL here. */
1688 if (waitpid(tcp->pid, &status, 0) < 0) {
1689 if (errno != ECHILD) {
1690 perror("detach: waiting");
1691 break;
1692 }
1693#ifdef __WCLONE
1694 /* If no processes, try clones. */
1695 if (wait4(tcp->pid, &status, __WCLONE,
1696 NULL) < 0) {
1697 if (errno != ECHILD)
1698 perror("detach: waiting");
1699 break;
1700 }
1701#endif /* __WCLONE */
1702 }
1703#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001704 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001705#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706 if (!WIFSTOPPED(status)) {
1707 /* Au revoir, mon ami. */
1708 break;
1709 }
1710 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001711 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001712 break;
1713 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001714 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001715 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001716 : WSTOPSIG(status));
1717 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001720 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001721#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722
1723#if defined(SUNOS4)
1724 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1725 if (sig && kill(tcp->pid, sig) < 0)
1726 perror("detach: kill");
1727 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001728 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729#endif /* SUNOS4 */
1730
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731 if (!qflag)
1732 fprintf(stderr, "Process %u detached\n", tcp->pid);
1733
1734 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001735
1736#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001737 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001738 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001739 droptcb(zombie);
1740 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001741#endif
1742
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743 return error;
1744}
1745
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001746#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001747
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001748static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749{
1750 int pid;
1751 int status;
1752
1753 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754 }
1755}
1756
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001757#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
1759static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001760cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761{
1762 int i;
1763 struct tcb *tcp;
1764
Roland McGrathee9d4352002-12-18 04:16:10 +00001765 for (i = 0; i < tcbtabsize; i++) {
1766 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 if (!(tcp->flags & TCB_INUSE))
1768 continue;
1769 if (debug)
1770 fprintf(stderr,
1771 "cleanup: looking at pid %u\n", tcp->pid);
1772 if (tcp_last &&
1773 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001774 tprintf(" <unfinished ...>");
1775 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776 }
1777 if (tcp->flags & TCB_ATTACHED)
1778 detach(tcp, 0);
1779 else {
1780 kill(tcp->pid, SIGCONT);
1781 kill(tcp->pid, SIGTERM);
1782 }
1783 }
1784 if (cflag)
1785 call_summary(outf);
1786}
1787
1788static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001789interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790{
1791 interrupted = 1;
1792}
1793
1794#ifndef HAVE_STRERROR
1795
Roland McGrath6d2b3492002-12-30 00:51:30 +00001796#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797extern int sys_nerr;
1798extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001799#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800
1801const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001802strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803{
1804 static char buf[64];
1805
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001806 if (err_no < 1 || err_no >= sys_nerr) {
1807 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808 return buf;
1809 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001810 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001811}
1812
1813#endif /* HAVE_STERRROR */
1814
1815#ifndef HAVE_STRSIGNAL
1816
Roland McGrath8f474e02003-01-14 07:53:33 +00001817#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001818extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001820#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1821extern char *_sys_siglist[];
1822#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823
1824const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001825strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826{
1827 static char buf[64];
1828
1829 if (sig < 1 || sig >= NSIG) {
1830 sprintf(buf, "Unknown signal %d", sig);
1831 return buf;
1832 }
1833#ifdef HAVE__SYS_SIGLIST
1834 return _sys_siglist[sig];
1835#else
1836 return sys_siglist[sig];
1837#endif
1838}
1839
1840#endif /* HAVE_STRSIGNAL */
1841
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001842#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843
1844static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001845rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001846{
1847 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848
Roland McGrathee9d4352002-12-18 04:16:10 +00001849 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001850 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001851 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001852 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001853 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001854 }
1855
Roland McGrathca16be82003-01-10 19:55:28 +00001856 for (i = j = 0; i < tcbtabsize; i++) {
1857 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001858 if (!(tcp->flags & TCB_INUSE))
1859 continue;
1860 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001861 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862 j++;
1863 }
1864 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001865 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866 }
1867}
1868
1869#ifndef HAVE_POLLABLE_PROCFS
1870
1871static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001872proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874 int i;
1875
1876 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001877 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878 }
1879 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001880 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001881 }
1882}
1883
1884static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001885proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886{
1887 int i;
1888 int n;
1889 struct proc_pollfd pollinfo;
1890
1891 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1892 return n;
1893 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001894 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001895 }
1896 for (i = 0; i < nprocs; i++) {
1897 if (pollv[i].fd == pollinfo.fd)
1898 pollv[i].revents = pollinfo.revents;
1899 else
1900 pollv[i].revents = 0;
1901 }
1902 poller_pid = pollinfo.pid;
1903 return 1;
1904}
1905
1906static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001907wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001908{
1909}
1910
1911static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001912proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913{
1914 struct proc_pollfd pollinfo;
1915 struct sigaction sa;
1916 sigset_t blocked_set, empty_set;
1917 int i;
1918 int n;
1919 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001920#ifdef FREEBSD
1921 struct procfs_status pfs;
1922#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923
1924 switch (fork()) {
1925 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001926 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927 case 0:
1928 break;
1929 default:
1930 return;
1931 }
1932
1933 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1934 sa.sa_flags = 0;
1935 sigemptyset(&sa.sa_mask);
1936 sigaction(SIGHUP, &sa, NULL);
1937 sigaction(SIGINT, &sa, NULL);
1938 sigaction(SIGQUIT, &sa, NULL);
1939 sigaction(SIGPIPE, &sa, NULL);
1940 sigaction(SIGTERM, &sa, NULL);
1941 sa.sa_handler = wakeup_handler;
1942 sigaction(SIGUSR1, &sa, NULL);
1943 sigemptyset(&blocked_set);
1944 sigaddset(&blocked_set, SIGUSR1);
1945 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1946 sigemptyset(&empty_set);
1947
1948 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001949 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001950 }
1951 n = rl.rlim_cur;
1952 for (i = 0; i < n; i++) {
1953 if (i != pfd && i != proc_poll_pipe[1])
1954 close(i);
1955 }
1956
1957 pollinfo.fd = pfd;
1958 pollinfo.pid = getpid();
1959 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001960#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001961 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1962#else
1963 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1964#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001965 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 switch (errno) {
1967 case EINTR:
1968 continue;
1969 case EBADF:
1970 pollinfo.revents = POLLERR;
1971 break;
1972 case ENOENT:
1973 pollinfo.revents = POLLHUP;
1974 break;
1975 default:
1976 perror("proc_poller: PIOCWSTOP");
1977 }
1978 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1979 _exit(0);
1980 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001981 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001982 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1983 sigsuspend(&empty_set);
1984 }
1985}
1986
1987#endif /* !HAVE_POLLABLE_PROCFS */
1988
1989static int
1990choose_pfd()
1991{
1992 int i, j;
1993 struct tcb *tcp;
1994
1995 static int last;
1996
1997 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001998 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001999 /*
2000 * The previous process is ready to run again. We'll
2001 * let it do so if it is currently in a syscall. This
2002 * heuristic improves the readability of the trace.
2003 */
2004 tcp = pfd2tcb(pollv[last].fd);
2005 if (tcp && (tcp->flags & TCB_INSYSCALL))
2006 return pollv[last].fd;
2007 }
2008
2009 for (i = 0; i < nprocs; i++) {
2010 /* Let competing children run round robin. */
2011 j = (i + last + 1) % nprocs;
2012 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2013 tcp = pfd2tcb(pollv[j].fd);
2014 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002015 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016 }
2017 droptcb(tcp);
2018 return -1;
2019 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002020 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 last = j;
2022 return pollv[j].fd;
2023 }
2024 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002025 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026}
2027
2028static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002029trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002030{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002031#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002032 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002033#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 struct tcb *tcp;
2035 int pfd;
2036 int what;
2037 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002038 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039
2040 for (;;) {
2041 if (interactive)
2042 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2043
2044 if (nprocs == 0)
2045 break;
2046
2047 switch (nprocs) {
2048 case 1:
2049#ifndef HAVE_POLLABLE_PROCFS
2050 if (proc_poll_pipe[0] == -1) {
2051#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002052 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 if (!tcp)
2054 continue;
2055 pfd = tcp->pfd;
2056 if (pfd == -1)
2057 continue;
2058 break;
2059#ifndef HAVE_POLLABLE_PROCFS
2060 }
2061 /* fall through ... */
2062#endif /* !HAVE_POLLABLE_PROCFS */
2063 default:
2064#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002065#ifdef POLL_HACK
2066 /* On some systems (e.g. UnixWare) we get too much ugly
2067 "unfinished..." stuff when multiple proceses are in
2068 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002069
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002070 if (in_syscall) {
2071 struct pollfd pv;
2072 tcp = in_syscall;
2073 in_syscall = NULL;
2074 pv.fd = tcp->pfd;
2075 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002076 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002077 if (interrupted)
2078 return 0;
2079 continue;
2080 }
2081 else if (what == 1 && pv.revents & POLLWANT) {
2082 goto FOUND;
2083 }
2084 }
2085#endif
2086
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002087 if (poll(pollv, nprocs, INFTIM) < 0) {
2088 if (interrupted)
2089 return 0;
2090 continue;
2091 }
2092#else /* !HAVE_POLLABLE_PROCFS */
2093 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2094 if (interrupted)
2095 return 0;
2096 continue;
2097 }
2098#endif /* !HAVE_POLLABLE_PROCFS */
2099 pfd = choose_pfd();
2100 if (pfd == -1)
2101 continue;
2102 break;
2103 }
2104
2105 /* Look up `pfd' in our table. */
2106 if ((tcp = pfd2tcb(pfd)) == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002107 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002108 }
John Hughesb6643082002-05-23 11:02:22 +00002109#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002110 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002111#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112 /* Get the status of the process. */
2113 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002114#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002115 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002116#else /* FREEBSD */
2117 /* Thanks to some scheduling mystery, the first poller
2118 sometimes waits for the already processed end of fork
2119 event. Doing a non blocking poll here solves the problem. */
2120 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002121 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002122 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002123 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002124#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002125 ioctl_errno = errno;
2126#ifndef HAVE_POLLABLE_PROCFS
2127 if (proc_poll_pipe[0] != -1) {
2128 if (ioctl_result < 0)
2129 kill(poller_pid, SIGKILL);
2130 else
2131 kill(poller_pid, SIGUSR1);
2132 }
2133#endif /* !HAVE_POLLABLE_PROCFS */
2134 }
2135 if (interrupted)
2136 return 0;
2137
2138 if (interactive)
2139 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2140
2141 if (ioctl_result < 0) {
2142 /* Find out what happened if it failed. */
2143 switch (ioctl_errno) {
2144 case EINTR:
2145 case EBADF:
2146 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002147#ifdef FREEBSD
2148 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002149#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002150 case ENOENT:
2151 droptcb(tcp);
2152 continue;
2153 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002154 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002155 }
2156 }
2157
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002158#ifdef FREEBSD
2159 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2160 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002161 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002162 continue;
2163 }
Roland McGrath553a6092002-12-16 20:40:39 +00002164#endif
2165
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002166 /* clear the just started flag */
2167 tcp->flags &= ~TCB_STARTUP;
2168
2169 /* set current output file */
2170 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002171 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172
2173 if (cflag) {
2174 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002175#ifdef FREEBSD
2176 char buf[1024];
2177 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002178
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002179 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2180 buf[len] = '\0';
2181 sscanf(buf,
2182 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2183 &stime.tv_sec, &stime.tv_usec);
2184 } else
2185 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002186#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2188 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002189#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002190 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2191 tcp->stime = stime;
2192 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002193 what = tcp->status.PR_WHAT;
2194 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002195#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002196 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002197 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2198 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002200 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 }
2202 }
2203 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002204#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002205 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002206#ifdef POLL_HACK
2207 in_syscall = tcp;
2208#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209 case PR_SYSEXIT:
2210 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002211 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 }
2213 break;
2214 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002215 if (cflag != CFLAG_ONLY_STATS
2216 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002217 printleader(tcp);
2218 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002219 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002220 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002221#ifdef PR_INFO
2222 if (tcp->status.PR_INFO.si_signo == what) {
2223 printleader(tcp);
2224 tprintf(" siginfo=");
2225 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002226 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002227 }
2228#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 }
2230 break;
2231 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002232 if (cflag != CFLAGS_ONLY_STATS
2233 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 printleader(tcp);
2235 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002236 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002237 }
2238 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002239#ifdef FREEBSD
2240 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002241 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002242#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002243 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002244 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245 break;
2246 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002247 /* Remember current print column before continuing. */
2248 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002249 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002250#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002251 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002252#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002253 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002254#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002255 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002256 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002257 }
2258 }
2259 return 0;
2260}
2261
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002262#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002263
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002264#ifdef TCB_GROUP_EXITING
2265/* Handle an exit detach or death signal that is taking all the
2266 related clone threads with it. This is called in three circumstances:
2267 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2268 SIG == 0 Continuing TCP will perform an exit_group syscall.
2269 SIG == other Continuing TCP with SIG will kill the process.
2270*/
2271static int
2272handle_group_exit(struct tcb *tcp, int sig)
2273{
2274 /* We need to locate our records of all the clone threads
2275 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002276 struct tcb *leader = NULL;
2277
2278 if (tcp->flags & TCB_CLONE_THREAD)
2279 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002280
2281 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002282 if (leader != NULL && leader != tcp
2283 && !(leader->flags & TCB_GROUP_EXITING)
2284 && !(tcp->flags & TCB_STARTUP)
2285 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002286 fprintf(stderr,
2287 "PANIC: handle_group_exit: %d leader %d\n",
2288 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002289 }
2290 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002291 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002292 }
2293 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002294 /* Mark that we are taking the process down. */
2295 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002296 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002297 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002298 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002299 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002300 } else {
2301 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2302 cleanup();
2303 return -1;
2304 }
2305 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002306 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002307 if (leader != tcp)
2308 droptcb(tcp);
2309 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002310 /* The leader will report to us as parent now,
2311 and then we'll get to the SIG==-1 case. */
2312 return 0;
2313 }
2314 }
2315
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002316 return 0;
2317}
2318#endif
2319
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002320#ifdef LINUX
2321static int
2322handle_ptrace_event(int status, struct tcb *tcp)
2323{
2324 if (status >> 16 == PTRACE_EVENT_VFORK ||
2325 status >> 16 == PTRACE_EVENT_CLONE ||
2326 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002327 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002328
2329 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2330 if (errno != ESRCH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002331 error_msg_and_die("Cannot get new child's pid");
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002332 }
2333 return -1;
2334 }
2335 return handle_new_child(tcp, childpid, 0);
2336 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002337 if (status >> 16 == PTRACE_EVENT_EXEC) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002338 return 0;
2339 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002340 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2341 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002342 return 1;
2343}
2344#endif
2345
Roland McGratheb9e2e82009-06-02 16:49:22 -07002346static int
2347trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348{
2349 int pid;
2350 int wait_errno;
2351 int status;
2352 struct tcb *tcp;
2353#ifdef LINUX
2354 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002355#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002356 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002357#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002358#endif /* LINUX */
2359
Roland McGratheb9e2e82009-06-02 16:49:22 -07002360 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002361 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002362 return 0;
2363 if (interactive)
2364 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002365#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002366#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002367 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002368 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002369 /* this kernel does not support __WALL */
2370 wait4_options &= ~__WALL;
2371 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002372 pid = wait4(-1, &status, wait4_options,
2373 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002374 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002375 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002376 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002377 pid = wait4(-1, &status, __WCLONE,
2378 cflag ? &ru : NULL);
2379 if (pid == -1) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002380 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002381 }
2382 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002383#else
2384 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2385#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386#endif /* LINUX */
2387#ifdef SUNOS4
2388 pid = wait(&status);
2389#endif /* SUNOS4 */
2390 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002391 if (interactive)
2392 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002393
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002395 switch (wait_errno) {
2396 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002397 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002398 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002399 /*
2400 * We would like to verify this case
2401 * but sometimes a race in Solbourne's
2402 * version of SunOS sometimes reports
2403 * ECHILD before sending us SIGCHILD.
2404 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002405 return 0;
2406 default:
2407 errno = wait_errno;
2408 perror("strace: wait");
2409 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002410 }
2411 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002412 if (pid == popen_pid) {
2413 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002414 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002415 continue;
2416 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002417 if (debug) {
2418 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2419#ifdef LINUX
2420 unsigned ev = (unsigned)status >> 16;
2421 if (ev) {
2422 static const char *const event_names[] = {
2423 [PTRACE_EVENT_CLONE] = "CLONE",
2424 [PTRACE_EVENT_FORK] = "FORK",
2425 [PTRACE_EVENT_VFORK] = "VFORK",
2426 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2427 [PTRACE_EVENT_EXEC] = "EXEC",
2428 [PTRACE_EVENT_EXIT] = "EXIT",
2429 };
2430 const char *e;
2431 if (ev < ARRAY_SIZE(event_names))
2432 e = event_names[ev];
2433 else {
2434 sprintf(buf, "?? (%u)", ev);
2435 e = buf;
2436 }
2437 fprintf(stderr, " PTRACE_EVENT_%s", e);
2438 }
2439#endif
2440 strcpy(buf, "???");
2441 if (WIFSIGNALED(status))
2442#ifdef WCOREDUMP
2443 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2444 WCOREDUMP(status) ? "core," : "",
2445 signame(WTERMSIG(status)));
2446#else
2447 sprintf(buf, "WIFSIGNALED,sig=%s",
2448 signame(WTERMSIG(status)));
2449#endif
2450 if (WIFEXITED(status))
2451 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2452 if (WIFSTOPPED(status))
2453 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
2454 if (WIFCONTINUED(status))
2455 strcpy(buf, "WIFCONTINUED");
2456 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2457 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002458
2459 /* Look up `pid' in our table. */
2460 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002461#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002462 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002463 /* This is needed to go with the CLONE_PTRACE
2464 changes in process.c/util.c: we might see
2465 the child's initial trap before we see the
2466 parent return from the clone syscall.
2467 Leave the child suspended until the parent
2468 returns from its system call. Only then
2469 will we have the association of parent and
2470 child so that we know how to do clearbpt
2471 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002472 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002473 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002474 if (!qflag)
2475 fprintf(stderr, "\
2476Process %d attached (waiting for parent)\n",
2477 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002478 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002479 else
2480 /* This can happen if a clone call used
2481 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002482#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002483 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002484 if (WIFSTOPPED(status))
2485 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002486 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002487 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002489 /* set current output file */
2490 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002491 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002492 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002493#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002494 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2495 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002496#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002497 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002498
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499 if (tcp->flags & TCB_SUSPENDED) {
2500 /*
2501 * Apparently, doing any ptrace() call on a stopped
2502 * process, provokes the kernel to report the process
2503 * status again on a subsequent wait(), even if the
2504 * process has not been actually restarted.
2505 * Since we have inspected the arguments of suspended
2506 * processes we end up here testing for this case.
2507 */
2508 continue;
2509 }
2510 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002511 if (pid == strace_child)
2512 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002513 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002514 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2515 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002516 tprintf("+++ killed by %s %s+++",
2517 signame(WTERMSIG(status)),
2518#ifdef WCOREDUMP
2519 WCOREDUMP(status) ? "(core dumped) " :
2520#endif
2521 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002522 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002523 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002524#ifdef TCB_GROUP_EXITING
2525 handle_group_exit(tcp, -1);
2526#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002527 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002528#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002529 continue;
2530 }
2531 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002532 if (pid == strace_child)
2533 exit_code = WEXITSTATUS(status);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002534 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002535#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002536 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002537 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002538#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002539 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002541 "PANIC: attached pid %u exited with %d\n",
2542 pid, WEXITSTATUS(status));
2543 }
Roland McGrath0a396902003-06-10 03:05:53 +00002544 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002545 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002546 tprintf(" <unfinished ... exit status %d>\n",
2547 WEXITSTATUS(status));
2548 tcp_last = NULL;
2549 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002550#ifdef TCB_GROUP_EXITING
2551 handle_group_exit(tcp, -1);
2552#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002554#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002555 continue;
2556 }
2557 if (!WIFSTOPPED(status)) {
2558 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2559 droptcb(tcp);
2560 continue;
2561 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002562
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002563 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002564 if (handle_ptrace_event(status, tcp) != 1)
2565 goto tracing;
2566 }
2567
Roland McGrath02203312007-06-11 22:06:31 +00002568 /*
2569 * Interestingly, the process may stop
2570 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002571 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002572 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002573 * A no-MMU vforked child won't send up a signal,
2574 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002575 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002576 if ((tcp->flags & TCB_STARTUP) &&
2577 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002578 /*
2579 * This flag is there to keep us in sync.
2580 * Next time this process stops it should
2581 * really be entering a system call.
2582 */
2583 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002585 /*
2586 * One example is a breakpoint inherited from
2587 * parent through fork ().
2588 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002589 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2590 droptcb(tcp);
2591 cleanup();
2592 return -1;
2593 }
2594 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002595#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002596 /* If options were not set for this tracee yet */
2597 if (tcp->parent == NULL) {
2598 if (ptrace_setoptions) {
2599 if (debug)
2600 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2601 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2602 if (errno != ESRCH) {
2603 /* Should never happen, really */
2604 perror_msg_and_die("PTRACE_SETOPTIONS");
2605 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002606 }
2607 }
2608 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002609#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002610 goto tracing;
2611 }
2612
Denys Vlasenko75422762011-05-27 14:36:01 +02002613 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002614 if (WSTOPSIG(status) == SIGSTOP &&
2615 (tcp->flags & TCB_SIGTRAPPED)) {
2616 /*
2617 * Trapped attempt to block SIGTRAP
2618 * Hope we are back in control now.
2619 */
2620 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002621 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002622 cleanup();
2623 return -1;
2624 }
2625 continue;
2626 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002627 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002628 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002629 siginfo_t si;
2630#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002631 long pc = 0;
2632 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002633
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002634 upeek(tcp, PT_CR_IPSR, &psr);
2635 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002636
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002637# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002638 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002639# define PC_FORMAT_STR " @ %lx"
2640# define PC_FORMAT_ARG pc
2641#else
2642# define PC_FORMAT_STR "%s"
2643# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002644#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002645 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002646 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2647 tprintf("--- ");
2648 printsiginfo(&si, verbose(tcp));
2649 tprintf(" (%s)" PC_FORMAT_STR " ---",
2650 strsignal(WSTOPSIG(status)),
2651 PC_FORMAT_ARG);
2652 } else
2653 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2654 strsignal(WSTOPSIG(status)),
2655 signame(WSTOPSIG(status)),
2656 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002657 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002658 }
Roland McGrath05690952004-10-20 01:00:27 +00002659 if (((tcp->flags & TCB_ATTACHED) ||
2660 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002662#ifdef TCB_GROUP_EXITING
2663 handle_group_exit(tcp, WSTOPSIG(status));
2664#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002665 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002666#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002667 continue;
2668 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002669 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670 cleanup();
2671 return -1;
2672 }
2673 tcp->flags &= ~TCB_SUSPENDED;
2674 continue;
2675 }
Roland McGrath02203312007-06-11 22:06:31 +00002676 /* we handled the STATUS, we are permitted to interrupt now. */
2677 if (interrupted)
2678 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002679 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2680 /* ptrace() failed in trace_syscall() with ESRCH.
2681 * Likely a result of process disappearing mid-flight.
2682 * Observed case: exit_group() terminating
2683 * all processes in thread group. In this case, threads
2684 * "disappear" in an unpredictable moment without any
2685 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002686 */
2687 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002688 if (tcp_last) {
2689 /* Do we have dangling line "syscall(param, param"?
2690 * Finish the line then. We cannot
2691 */
2692 tcp_last->flags |= TCB_REPRINT;
2693 tprintf(" <unfinished ...>");
2694 printtrailer();
2695 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002696 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002697 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002698 ptrace(PTRACE_KILL,
2699 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002700 droptcb(tcp);
2701 }
2702 continue;
2703 }
2704 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002705#ifdef TCB_GROUP_EXITING
2706 if (tcp->flags & TCB_GROUP_EXITING) {
2707 if (handle_group_exit(tcp, 0) < 0)
2708 return -1;
2709 continue;
2710 }
2711#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002712 if (tcp->flags & TCB_ATTACHED)
2713 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002714 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002715 cleanup();
2716 return -1;
2717 }
2718 continue;
2719 }
2720 if (tcp->flags & TCB_SUSPENDED) {
2721 if (!qflag)
2722 fprintf(stderr, "Process %u suspended\n", pid);
2723 continue;
2724 }
2725 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002726 /* Remember current print column before continuing. */
2727 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002728 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002729 cleanup();
2730 return -1;
2731 }
2732 }
2733 return 0;
2734}
2735
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002736#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002737
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002738#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002739
2740void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002741tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002742{
2743 va_list args;
2744
Andreas Schwabe5355de2009-10-27 16:56:43 +01002745 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002746 if (outf) {
2747 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002748 if (n < 0) {
2749 if (outf != stderr)
2750 perror(outfname == NULL
2751 ? "<writing to pipe>" : outfname);
2752 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002753 curcol += n;
2754 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002755 va_end(args);
2756 return;
2757}
2758
2759void
Denys Vlasenko12014262011-05-30 14:00:14 +02002760printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002761{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002762 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002763 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002764 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002765 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002766 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002767 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002768 tprintf("= ? <unavailable>\n");
2769 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002770 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002771 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002772 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002773 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002774 }
2775 curcol = 0;
2776 if ((followfork == 1 || pflag_seen > 1) && outfname)
2777 tprintf("%-5d ", tcp->pid);
2778 else if (nprocs > 1 && !outfname)
2779 tprintf("[pid %5u] ", tcp->pid);
2780 if (tflag) {
2781 char str[sizeof("HH:MM:SS")];
2782 struct timeval tv, dtv;
2783 static struct timeval otv;
2784
2785 gettimeofday(&tv, NULL);
2786 if (rflag) {
2787 if (otv.tv_sec == 0)
2788 otv = tv;
2789 tv_sub(&dtv, &tv, &otv);
2790 tprintf("%6ld.%06ld ",
2791 (long) dtv.tv_sec, (long) dtv.tv_usec);
2792 otv = tv;
2793 }
2794 else if (tflag > 2) {
2795 tprintf("%ld.%06ld ",
2796 (long) tv.tv_sec, (long) tv.tv_usec);
2797 }
2798 else {
2799 time_t local = tv.tv_sec;
2800 strftime(str, sizeof(str), "%T", localtime(&local));
2801 if (tflag > 1)
2802 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2803 else
2804 tprintf("%s ", str);
2805 }
2806 }
2807 if (iflag)
2808 printcall(tcp);
2809}
2810
2811void
Denys Vlasenko12014262011-05-30 14:00:14 +02002812tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002813{
2814 if (curcol < col)
2815 tprintf("%*s", col - curcol, "");
2816}
2817
2818void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002819printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002820{
2821 tprintf("\n");
2822 tcp_last = NULL;
2823}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002824
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002825#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002826
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002827int
2828mp_ioctl(int fd, int cmd, void *arg, int size)
2829{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002830 struct iovec iov[2];
2831 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002832
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002833 iov[0].iov_base = &cmd;
2834 iov[0].iov_len = sizeof cmd;
2835 if (arg) {
2836 ++n;
2837 iov[1].iov_base = arg;
2838 iov[1].iov_len = size;
2839 }
Roland McGrath553a6092002-12-16 20:40:39 +00002840
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002841 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002842}
2843
2844#endif