blob: d353eacffb0ca5471574fd5fc7add60e4dc32136 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
52# if defined __NR_tgkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020053# define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# elif defined __NR_tkill
Denys Vlasenkob63256e2011-06-07 12:13:24 +020055# define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000056# else
57 /* kill() may choose arbitrarily the target task of the process group
58 while we later wait on a that specific TID. PID process waits become
59 TID task specific waits for a process under ptrace(2). */
60# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenkob63256e2011-06-07 12:13:24 +020061# define my_tgkill(pid, tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000062# endif
63#endif
64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000065#if defined(IA64) && defined(LINUX)
66# include <asm/ptrace_offsets.h>
67#endif
68
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000069#ifdef USE_PROCFS
70#include <poll.h>
71#endif
72
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#ifdef SVR4
74#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000075#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000076#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000077#include <sys/uio.h>
78#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000080#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000082extern int optind;
83extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085
Roland McGrath41c48222008-07-18 00:25:10 +000086int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020087unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020088/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020089static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000090int dtime = 0, xflag = 0, qflag = 0;
91cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000092static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000093/*
94 * daemonized_tracer supports -D option.
95 * With this option, strace forks twice.
96 * Unlike normal case, with -D *grandparent* process exec's,
97 * becoming a traced process. Child exits (this prevents traced process
98 * from having children it doesn't expect to have), and grandchild
99 * attaches to grandparent similarly to strace -p PID.
100 * This allows for more transparent interaction in cases
101 * when process and its parent are communicating via signals,
102 * wait() etc. Without -D, strace process gets lodged in between,
103 * disrupting parent<->child link.
104 */
105static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000107/* Sometimes we want to print only succeeding syscalls. */
108int not_failing_only = 0;
109
Grant Edwards8a082772011-04-07 20:25:40 +0000110/* Show path associated with fd arguments */
111int show_fd_path = 0;
112
113/* are we filtering traces based on paths? */
114int tracing_paths = 0;
115
Dmitry V. Levina6809652008-11-10 17:14:58 +0000116static int exit_code = 0;
117static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200118static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700119
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000120static char *username = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121uid_t run_uid;
122gid_t run_gid;
123
124int acolumn = DEFAULT_ACOLUMN;
125int max_strlen = DEFAULT_STRLEN;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Roland McGrathee9d4352002-12-18 04:16:10 +0000129struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200130static unsigned int nprocs, tcbtabsize;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000131const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Andreas Schwabe5355de2009-10-27 16:56:43 +0100133static int detach(struct tcb *tcp, int sig);
134static int trace(void);
135static void cleanup(void);
136static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137static sigset_t empty_set, blocked_set;
138
139#ifdef HAVE_SIG_ATOMIC_T
140static volatile sig_atomic_t interrupted;
141#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143#endif /* !HAVE_SIG_ATOMIC_T */
144
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000145#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146
Andreas Schwabe5355de2009-10-27 16:56:43 +0100147static struct tcb *pfd2tcb(int pfd);
148static void reaper(int sig);
149static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000150static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#ifndef HAVE_POLLABLE_PROCFS
153
Andreas Schwabe5355de2009-10-27 16:56:43 +0100154static void proc_poll_open(void);
155static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156
157struct proc_pollfd {
158 int fd;
159 int revents;
160 int pid;
161};
162
163static int poller_pid;
164static int proc_poll_pipe[2] = { -1, -1 };
165
166#endif /* !HAVE_POLLABLE_PROCFS */
167
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000168#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000169#define POLLWANT POLLWRNORM
170#else
171#define POLLWANT POLLPRI
172#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000173#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174
175static void
176usage(ofp, exitval)
177FILE *ofp;
178int exitval;
179{
180 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000181usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000183 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200184 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000185 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200187-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-f -- follow forks, -ff -- with output into separate files\n\
189-F -- attempt to follow vforks, -h -- print help message\n\
190-i -- print instruction pointer at time of syscall\n\
191-q -- suppress messages about attaching, detaching, etc.\n\
192-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
193-T -- print time spent in each syscall, -V -- print version\n\
194-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
195-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000196-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197-a column -- alignment COLUMN for printing syscall results (default %d)\n\
198-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
199 options: trace, abbrev, verbose, raw, signal, read, or write\n\
200-o file -- send trace output to FILE instead of stderr\n\
201-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
202-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000203-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
205-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
206-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000207-E var=val -- put var=val in the environment for command\n\
208-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000209-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000210" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000211-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000212 */
213, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214 exit(exitval);
215}
216
Denys Vlasenko75422762011-05-27 14:36:01 +0200217static void die(void) __attribute__ ((noreturn));
218static void die(void)
219{
220 if (strace_tracer_pid == getpid()) {
221 cflag = 0;
222 cleanup();
223 }
224 exit(1);
225}
226
227static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200228{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000229 fflush(NULL);
230 fprintf(stderr, "%s: ", progname);
231 vfprintf(stderr, fmt, p);
232 if (err_no)
233 fprintf(stderr, ": %s\n", strerror(err_no));
234 else
235 putc('\n', stderr);
236 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200237}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200238
Denys Vlasenko75422762011-05-27 14:36:01 +0200239void error_msg(const char *fmt, ...)
240{
241 va_list p;
242 va_start(p, fmt);
243 verror_msg(0, fmt, p);
244 va_end(p);
245}
246
247void error_msg_and_die(const char *fmt, ...)
248{
249 va_list p;
250 va_start(p, fmt);
251 verror_msg(0, fmt, p);
252 die();
253}
254
255void perror_msg(const char *fmt, ...)
256{
257 va_list p;
258 va_start(p, fmt);
259 verror_msg(errno, fmt, p);
260 va_end(p);
261}
262
263void perror_msg_and_die(const char *fmt, ...)
264{
265 va_list p;
266 va_start(p, fmt);
267 verror_msg(errno, fmt, p);
268 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200269}
270
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000271#ifdef SVR4
272#ifdef MIPS
273void
274foobar()
275{
276}
277#endif /* MIPS */
278#endif /* SVR4 */
279
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400280/* Glue for systems without a MMU that cannot provide fork() */
281#ifdef HAVE_FORK
282# define strace_vforked 0
283#else
284# define strace_vforked 1
285# define fork() vfork()
286#endif
287
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200288static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000289set_cloexec_flag(int fd)
290{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200291 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000292
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200293 flags = fcntl(fd, F_GETFD);
294 if (flags < 0) {
295 /* Can happen only if fd is bad.
296 * Should never happen: if it does, we have a bug
297 * in the caller. Therefore we just abort
298 * instead of propagating the error.
299 */
300 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000301 }
302
303 newflags = flags | FD_CLOEXEC;
304 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200305 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000306
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200307 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000308}
309
310/*
311 * When strace is setuid executable, we have to swap uids
312 * before and after filesystem and process management operations.
313 */
314static void
315swap_uid(void)
316{
317#ifndef SVR4
318 int euid = geteuid(), uid = getuid();
319
320 if (euid != uid && setreuid(euid, uid) < 0)
321 {
322 fprintf(stderr, "%s: setreuid: %s\n",
323 progname, strerror(errno));
324 exit(1);
325 }
326#endif
327}
328
Roland McGrath4bfa6262007-07-05 20:03:16 +0000329#if _LFS64_LARGEFILE
330# define fopen_for_output fopen64
331#else
332# define fopen_for_output fopen
333#endif
334
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000335static FILE *
336strace_fopen(const char *path, const char *mode)
337{
338 FILE *fp;
339
340 swap_uid();
Roland McGrath4bfa6262007-07-05 20:03:16 +0000341 if ((fp = fopen_for_output(path, mode)) == NULL)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000342 fprintf(stderr, "%s: can't fopen '%s': %s\n",
343 progname, path, strerror(errno));
344 swap_uid();
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200345 if (fp)
346 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000347 return fp;
348}
349
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200350static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000351
352#ifndef _PATH_BSHELL
353# define _PATH_BSHELL "/bin/sh"
354#endif
355
356/*
357 * We cannot use standard popen(3) here because we have to distinguish
358 * popen child process from other processes we trace, and standard popen(3)
359 * does not export its child's pid.
360 */
361static FILE *
362strace_popen(const char *command)
363{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200364 FILE *fp;
365 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000366
367 swap_uid();
368 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200369 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200371 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000372
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200373 popen_pid = vfork();
374 if (popen_pid == -1)
375 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200377 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000378 /* child */
379 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200380 if (fds[0] != 0) {
381 if (dup2(fds[0], 0))
382 perror_msg_and_die("dup2");
383 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000384 }
385 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200386 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000387 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200388
389 /* parent */
390 close(fds[0]);
391 swap_uid();
392 fp = fdopen(fds[1], "w");
393 if (!fp)
394 error_msg_and_die("Out of memory");
395 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000396}
397
398static int
399newoutf(struct tcb *tcp)
400{
401 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000402 char name[520 + sizeof(int) * 3];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000403 FILE *fp;
404
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000405 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000406 if ((fp = strace_fopen(name, "w")) == NULL)
407 return -1;
408 tcp->outf = fp;
409 }
410 return 0;
411}
412
Roland McGrath02203312007-06-11 22:06:31 +0000413static void
414startup_attach(void)
415{
416 int tcbi;
417 struct tcb *tcp;
418
419 /*
420 * Block user interruptions as we would leave the traced
421 * process stopped (process state T) if we would terminate in
422 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200423 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000424 */
425 if (interactive)
426 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
427
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000428 if (daemonized_tracer) {
429 pid_t pid = fork();
430 if (pid < 0) {
431 _exit(1);
432 }
433 if (pid) { /* parent */
434 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200435 * Wait for grandchild to attach to straced process
436 * (grandparent). Grandchild SIGKILLs us after it attached.
437 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000438 * it proceeds to exec the straced program.
439 */
440 pause();
441 _exit(0); /* paranoia */
442 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200443 /* grandchild */
444 /* We will be the tracer process. Remember our new pid: */
445 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000446 }
447
Roland McGrath02203312007-06-11 22:06:31 +0000448 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
449 tcp = tcbtab[tcbi];
450 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
451 continue;
452#ifdef LINUX
453 if (tcp->flags & TCB_CLONE_THREAD)
454 continue;
455#endif
456 /* Reinitialize the output since it may have changed. */
457 tcp->outf = outf;
458 if (newoutf(tcp) < 0)
459 exit(1);
460
461#ifdef USE_PROCFS
462 if (proc_open(tcp, 1) < 0) {
463 fprintf(stderr, "trouble opening proc file\n");
464 droptcb(tcp);
465 continue;
466 }
467#else /* !USE_PROCFS */
468# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000469 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000470 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000471 DIR *dir;
472
473 sprintf(procdir, "/proc/%d/task", tcp->pid);
474 dir = opendir(procdir);
475 if (dir != NULL) {
476 unsigned int ntid = 0, nerr = 0;
477 struct dirent *de;
478 int tid;
479 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000480 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000481 continue;
482 tid = atoi(de->d_name);
483 if (tid <= 0)
484 continue;
485 ++ntid;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000486 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
Roland McGrath02203312007-06-11 22:06:31 +0000487 ++nerr;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000488 else if (tid != tcbtab[tcbi]->pid) {
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000489 tcp = alloctcb(tid);
Wang Chao21b8db42010-08-27 17:43:16 +0800490 tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
Roland McGrath02203312007-06-11 22:06:31 +0000491 tcbtab[tcbi]->nclone_threads++;
Roland McGrath02203312007-06-11 22:06:31 +0000492 tcp->parent = tcbtab[tcbi];
493 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000494 if (interactive) {
495 sigprocmask(SIG_SETMASK, &empty_set, NULL);
496 if (interrupted)
497 return;
498 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
499 }
Roland McGrath02203312007-06-11 22:06:31 +0000500 }
501 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000502 ntid -= nerr;
503 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000504 perror("attach: ptrace(PTRACE_ATTACH, ...)");
505 droptcb(tcp);
506 continue;
507 }
508 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000509 fprintf(stderr, ntid > 1
510? "Process %u attached with %u threads - interrupt to quit\n"
511: "Process %u attached - interrupt to quit\n",
512 tcbtab[tcbi]->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000513 }
514 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000515 } /* if (opendir worked) */
516 } /* if (-f) */
Roland McGrath02203312007-06-11 22:06:31 +0000517# endif
518 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
519 perror("attach: ptrace(PTRACE_ATTACH, ...)");
520 droptcb(tcp);
521 continue;
522 }
523 /* INTERRUPTED is going to be checked at the top of TRACE. */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000524
525 if (daemonized_tracer) {
526 /*
527 * It is our grandparent we trace, not a -p PID.
528 * Don't want to just detach on exit, so...
529 */
530 tcp->flags &= ~TCB_ATTACHED;
531 /*
532 * Make parent go away.
533 * Also makes grandparent's wait() unblock.
534 */
535 kill(getppid(), SIGKILL);
536 }
537
Roland McGrath02203312007-06-11 22:06:31 +0000538#endif /* !USE_PROCFS */
539 if (!qflag)
540 fprintf(stderr,
541 "Process %u attached - interrupt to quit\n",
542 tcp->pid);
543 }
544
545 if (interactive)
546 sigprocmask(SIG_SETMASK, &empty_set, NULL);
547}
548
549static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200550startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000551{
552 struct stat statbuf;
553 const char *filename;
554 char pathname[MAXPATHLEN];
555 int pid = 0;
556 struct tcb *tcp;
557
558 filename = argv[0];
559 if (strchr(filename, '/')) {
560 if (strlen(filename) > sizeof pathname - 1) {
561 errno = ENAMETOOLONG;
562 perror("strace: exec");
563 exit(1);
564 }
565 strcpy(pathname, filename);
566 }
567#ifdef USE_DEBUGGING_EXEC
568 /*
569 * Debuggers customarily check the current directory
570 * first regardless of the path but doing that gives
571 * security geeks a panic attack.
572 */
573 else if (stat(filename, &statbuf) == 0)
574 strcpy(pathname, filename);
575#endif /* USE_DEBUGGING_EXEC */
576 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000577 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000578 int m, n, len;
579
580 for (path = getenv("PATH"); path && *path; path += m) {
581 if (strchr(path, ':')) {
582 n = strchr(path, ':') - path;
583 m = n + 1;
584 }
585 else
586 m = n = strlen(path);
587 if (n == 0) {
588 if (!getcwd(pathname, MAXPATHLEN))
589 continue;
590 len = strlen(pathname);
591 }
592 else if (n > sizeof pathname - 1)
593 continue;
594 else {
595 strncpy(pathname, path, n);
596 len = n;
597 }
598 if (len && pathname[len - 1] != '/')
599 pathname[len++] = '/';
600 strcpy(pathname + len, filename);
601 if (stat(pathname, &statbuf) == 0 &&
602 /* Accept only regular files
603 with some execute bits set.
604 XXX not perfect, might still fail */
605 S_ISREG(statbuf.st_mode) &&
606 (statbuf.st_mode & 0111))
607 break;
608 }
609 }
610 if (stat(pathname, &statbuf) < 0) {
611 fprintf(stderr, "%s: %s: command not found\n",
612 progname, filename);
613 exit(1);
614 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000615 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000616 if (pid < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000617 perror("strace: fork");
618 cleanup();
619 exit(1);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000620 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200621 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
622 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000623 ) {
624 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000625#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200626 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000627#ifdef MIPS
628 /* Kludge for SGI, see proc_open for details. */
629 sa.sa_handler = foobar;
630 sa.sa_flags = 0;
631 sigemptyset(&sa.sa_mask);
632 sigaction(SIGINT, &sa, NULL);
633#endif /* MIPS */
634#ifndef FREEBSD
635 pause();
636#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000637 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000638#endif /* FREEBSD */
639#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200640 if (outf != stderr)
641 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000642
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000643 if (!daemonized_tracer) {
644 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
645 perror("strace: ptrace(PTRACE_TRACEME, ...)");
646 exit(1);
647 }
648 if (debug)
649 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000650 }
Roland McGrath02203312007-06-11 22:06:31 +0000651
652 if (username != NULL || geteuid() == 0) {
653 uid_t run_euid = run_uid;
654 gid_t run_egid = run_gid;
655
656 if (statbuf.st_mode & S_ISUID)
657 run_euid = statbuf.st_uid;
658 if (statbuf.st_mode & S_ISGID)
659 run_egid = statbuf.st_gid;
660
661 /*
662 * It is important to set groups before we
663 * lose privileges on setuid.
664 */
665 if (username != NULL) {
666 if (initgroups(username, run_gid) < 0) {
667 perror("initgroups");
668 exit(1);
669 }
670 if (setregid(run_gid, run_egid) < 0) {
671 perror("setregid");
672 exit(1);
673 }
674 if (setreuid(run_uid, run_euid) < 0) {
675 perror("setreuid");
676 exit(1);
677 }
678 }
679 }
680 else
681 setreuid(run_uid, run_uid);
682
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 if (!daemonized_tracer) {
684 /*
685 * Induce an immediate stop so that the parent
686 * will resume us with PTRACE_SYSCALL and display
687 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400688 * Unless of course we're on a no-MMU system where
689 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000690 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400691 if (!strace_vforked)
692 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000693 } else {
694 struct sigaction sv_sigchld;
695 sigaction(SIGCHLD, NULL, &sv_sigchld);
696 /*
697 * Make sure it is not SIG_IGN, otherwise wait
698 * will not block.
699 */
700 signal(SIGCHLD, SIG_DFL);
701 /*
702 * Wait for grandchild to attach to us.
703 * It kills child after that, and wait() unblocks.
704 */
705 alarm(3);
706 wait(NULL);
707 alarm(0);
708 sigaction(SIGCHLD, &sv_sigchld, NULL);
709 }
Roland McGrath02203312007-06-11 22:06:31 +0000710#endif /* !USE_PROCFS */
711
712 execv(pathname, argv);
713 perror("strace: exec");
714 _exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000715 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000716
717 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200718 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
719 strace_tracer_pid = getpid();
720
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000721 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722 if (daemonized_tracer) {
723 /* We want subsequent startup_attach() to attach to it. */
724 tcp->flags |= TCB_ATTACHED;
725 }
Roland McGrath02203312007-06-11 22:06:31 +0000726#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000727 if (proc_open(tcp, 0) < 0) {
728 fprintf(stderr, "trouble opening proc file\n");
729 cleanup();
730 exit(1);
Roland McGrath02203312007-06-11 22:06:31 +0000731 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000732#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000733}
734
Wang Chaob13c0de2010-11-12 17:25:19 +0800735#ifdef LINUX
736/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000737 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800738 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000739 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800740 */
741static int
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200742test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800743{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000744 int pid, expected_grandchild = 0, found_grandchild = 0;
745 const unsigned int test_options = PTRACE_O_TRACECLONE |
746 PTRACE_O_TRACEFORK |
747 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800748
749 if ((pid = fork()) < 0)
750 return -1;
751 else if (pid == 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000752 if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
Wang Chaob13c0de2010-11-12 17:25:19 +0800753 _exit(1);
Wang Chaob13c0de2010-11-12 17:25:19 +0800754 kill(getpid(), SIGSTOP);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000755 _exit(fork() < 0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800756 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000757
758 while (1) {
759 int status, tracee_pid;
760
761 tracee_pid = wait(&status);
762 if (tracee_pid == -1) {
763 if (errno == EINTR)
764 continue;
765 else if (errno == ECHILD)
766 break;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200767 perror("test_ptrace_setoptions_followfork");
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000768 return -1;
769 }
770 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000771 found_grandchild = tracee_pid;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000772 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
773 errno != ESRCH)
774 kill(tracee_pid, SIGKILL);
775 }
776 else if (WIFSTOPPED(status)) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000777 switch (WSTOPSIG(status)) {
778 case SIGSTOP:
779 if (ptrace(PTRACE_SETOPTIONS, pid,
780 NULL, test_options) < 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000781 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800782 return -1;
783 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000784 break;
785 case SIGTRAP:
786 if (status >> 16 == PTRACE_EVENT_FORK) {
787 long msg = 0;
788
789 if (ptrace(PTRACE_GETEVENTMSG, pid,
790 NULL, (long) &msg) == 0)
791 expected_grandchild = msg;
792 }
793 break;
Wang Chaob13c0de2010-11-12 17:25:19 +0800794 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000795 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
796 errno != ESRCH)
797 kill(pid, SIGKILL);
Wang Chaob13c0de2010-11-12 17:25:19 +0800798 }
799 }
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000800 if (expected_grandchild && expected_grandchild == found_grandchild)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200801 ptrace_setoptions |= test_options;
Wang Chaob13c0de2010-11-12 17:25:19 +0800802 return 0;
803}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200804
805/*
806 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
807 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
808 * and then see whether it will stop with (SIGTRAP | 0x80).
809 *
810 * Use of this option enables correct handling of user-generated SIGTRAPs,
811 * and SIGTRAPs generated by special instructions such as int3 on x86:
812 * _start: .globl _start
813 * int3
814 * movl $42, %ebx
815 * movl $1, %eax
816 * int $0x80
817 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
818 */
819static void
820test_ptrace_setoptions_for_all(void)
821{
822 const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
823 int pid;
824 int it_worked = 0;
825
826 pid = fork();
827 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200828 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200829
830 if (pid == 0) {
831 pid = getpid();
832 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200833 /* Note: exits with exitcode 1 */
834 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200835 kill(pid, SIGSTOP);
836 _exit(0); /* parent should see entry into this syscall */
837 }
838
839 while (1) {
840 int status, tracee_pid;
841
842 errno = 0;
843 tracee_pid = wait(&status);
844 if (tracee_pid <= 0) {
845 if (errno == EINTR)
846 continue;
847 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200848 perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200849 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200850 if (WIFEXITED(status)) {
851 if (WEXITSTATUS(status) == 0)
852 break;
853 /* PTRACE_TRACEME failed in child. This is fatal. */
854 exit(1);
855 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200856 if (!WIFSTOPPED(status)) {
857 kill(pid, SIGKILL);
858 error_msg_and_die("%s: unexpected wait status %x", __func__, status);
859 }
860 if (WSTOPSIG(status) == SIGSTOP) {
861 /*
862 * We don't check "options aren't accepted" error.
863 * If it happens, we'll never get (SIGTRAP | 0x80),
864 * and thus will decide to not use the option.
865 * IOW: the outcome of the test will be correct.
866 */
Denys Vlasenko75422762011-05-27 14:36:01 +0200867 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
868 if (errno != EINVAL)
869 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200870 }
871 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
872 it_worked = 1;
873 }
874 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
875 kill(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200876 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200877 }
878 }
879
880 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200881 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200882 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200883 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200884 fprintf(stderr, "ptrace_setoptions = %#x\n",
885 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200886 return;
887 }
888
889 fprintf(stderr,
890 "Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
891}
Wang Chaob13c0de2010-11-12 17:25:19 +0800892#endif
893
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000895main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897 struct tcb *tcp;
898 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000899 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900 struct sigaction sa;
901
902 static char buf[BUFSIZ];
903
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000904 progname = argv[0] ? argv[0] : "strace";
905
Denys Vlasenko75422762011-05-27 14:36:01 +0200906 strace_tracer_pid = getpid();
907
Roland McGrathee9d4352002-12-18 04:16:10 +0000908 /* Allocate the initial tcbtab. */
909 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000910 if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000911 fprintf(stderr, "%s: out of memory\n", progname);
912 exit(1);
913 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +0000914 if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000915 fprintf(stderr, "%s: out of memory\n", progname);
916 exit(1);
917 }
Roland McGrathee9d4352002-12-18 04:16:10 +0000918 for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
919 tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
920
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000921 outf = stderr;
922 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000923 set_sortby(DEFAULT_SORTBY);
924 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925 qualify("trace=all");
926 qualify("abbrev=all");
927 qualify("verbose=all");
928 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000929 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000930 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000931#ifndef USE_PROCFS
932 "D"
933#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000934 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935 switch (c) {
936 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000937 if (cflag == CFLAG_BOTH) {
938 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
939 progname);
940 exit(1);
941 }
942 cflag = CFLAG_ONLY_STATS;
943 break;
944 case 'C':
945 if (cflag == CFLAG_ONLY_STATS) {
946 fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
947 progname);
948 exit(1);
949 }
950 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 break;
952 case 'd':
953 debug++;
954 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000955#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000956 case 'D':
957 daemonized_tracer = 1;
958 break;
959#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000960 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000961 optF = 1;
962 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 case 'f':
964 followfork++;
965 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 case 'h':
967 usage(stdout, 0);
968 break;
969 case 'i':
970 iflag++;
971 break;
972 case 'q':
973 qflag++;
974 break;
975 case 'r':
976 rflag++;
977 tflag++;
978 break;
979 case 't':
980 tflag++;
981 break;
982 case 'T':
983 dtime++;
984 break;
985 case 'x':
986 xflag++;
987 break;
Grant Edwards8a082772011-04-07 20:25:40 +0000988 case 'y':
989 show_fd_path = 1;
990 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 case 'v':
992 qualify("abbrev=none");
993 break;
994 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +0000995 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 exit(0);
997 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000998 case 'z':
999 not_failing_only = 1;
1000 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001001 case 'a':
1002 acolumn = atoi(optarg);
1003 break;
1004 case 'e':
1005 qualify(optarg);
1006 break;
1007 case 'o':
1008 outfname = strdup(optarg);
1009 break;
1010 case 'O':
1011 set_overhead(atoi(optarg));
1012 break;
1013 case 'p':
Roland McGrathde6e5332003-01-24 04:31:23 +00001014 if ((pid = atoi(optarg)) <= 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 fprintf(stderr, "%s: Invalid process id: %s\n",
1016 progname, optarg);
1017 break;
1018 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001019 if (pid == strace_tracer_pid) {
Wichert Akkerman54a47671999-10-17 00:57:34 +00001020 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 break;
1022 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001023 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 tcp->flags |= TCB_ATTACHED;
1025 pflag_seen++;
1026 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001027 case 'P':
1028 tracing_paths = 1;
1029 if (pathtrace_select(optarg)) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001030 fprintf(stderr, "%s : failed to select path '%s'\n", progname, optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001031 exit(1);
1032 }
1033 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 case 's':
1035 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001036 if (max_strlen < 0) {
1037 fprintf(stderr,
1038 "%s: invalid -s argument: %s\n",
1039 progname, optarg);
1040 exit(1);
1041 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 break;
1043 case 'S':
1044 set_sortby(optarg);
1045 break;
1046 case 'u':
1047 username = strdup(optarg);
1048 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001049 case 'E':
1050 if (putenv(optarg) < 0) {
1051 fprintf(stderr, "%s: out of memory\n",
1052 progname);
1053 exit(1);
1054 }
1055 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 default:
1057 usage(stderr, 1);
1058 break;
1059 }
1060 }
1061
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001062 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001063 usage(stderr, 1);
1064
Wang Chaod322a4b2010-08-05 14:30:11 +08001065 if (pflag_seen && daemonized_tracer) {
1066 fprintf(stderr,
1067 "%s: -D and -p are mutually exclusive options\n",
1068 progname);
1069 exit(1);
1070 }
1071
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001072 if (!followfork)
1073 followfork = optF;
1074
Roland McGrathcb9def62006-04-25 07:48:03 +00001075 if (followfork > 1 && cflag) {
1076 fprintf(stderr,
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001077 "%s: (-c or -C) and -ff are mutually exclusive options\n",
Roland McGrathcb9def62006-04-25 07:48:03 +00001078 progname);
1079 exit(1);
1080 }
1081
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 /* See if they want to run as another user. */
1083 if (username != NULL) {
1084 struct passwd *pent;
1085
1086 if (getuid() != 0 || geteuid() != 0) {
1087 fprintf(stderr,
1088 "%s: you must be root to use the -u option\n",
1089 progname);
1090 exit(1);
1091 }
1092 if ((pent = getpwnam(username)) == NULL) {
1093 fprintf(stderr, "%s: cannot find user `%s'\n",
Roland McGrath09553f82007-07-05 19:31:49 +00001094 progname, username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095 exit(1);
1096 }
1097 run_uid = pent->pw_uid;
1098 run_gid = pent->pw_gid;
1099 }
1100 else {
1101 run_uid = getuid();
1102 run_gid = getgid();
1103 }
1104
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001105#ifdef LINUX
1106 if (followfork) {
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001107 if (test_ptrace_setoptions_followfork() < 0) {
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001108 fprintf(stderr,
1109 "Test for options supported by PTRACE_SETOPTIONS "
1110 "failed, giving up using this feature.\n");
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001111 ptrace_setoptions = 0;
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001112 }
1113 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001114 fprintf(stderr, "ptrace_setoptions = %#x\n",
1115 ptrace_setoptions);
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001116 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001117 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001118#endif
1119
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 /* Check if they want to redirect the output. */
1121 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001122 /* See if they want to pipe the output. */
1123 if (outfname[0] == '|' || outfname[0] == '!') {
1124 /*
1125 * We can't do the <outfname>.PID funny business
1126 * when using popen, so prohibit it.
1127 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001128 if (followfork > 1)
1129 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1130 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001131 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001132 else if (followfork <= 1 &&
1133 (outf = strace_fopen(outfname, "w")) == NULL)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134 exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 }
1136
Roland McGrath37b9a662003-11-07 02:26:54 +00001137 if (!outfname || outfname[0] == '|' || outfname[0] == '!')
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Roland McGrath37b9a662003-11-07 02:26:54 +00001139 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001142 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001143
Roland McGrath54cc1c82007-11-03 23:34:11 +00001144 /* Valid states here:
1145 optind < argc pflag_seen outfname interactive
1146 1 0 0 1
1147 0 1 0 1
1148 1 0 1 0
1149 0 1 1 1
1150 */
1151
1152 /* STARTUP_CHILD must be called before the signal handlers get
1153 installed below as they are inherited into the spawned process.
1154 Also we do not need to be protected by them as during interruption
1155 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1156 if (!pflag_seen)
1157 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 sigemptyset(&empty_set);
1160 sigemptyset(&blocked_set);
1161 sa.sa_handler = SIG_IGN;
1162 sigemptyset(&sa.sa_mask);
1163 sa.sa_flags = 0;
1164 sigaction(SIGTTOU, &sa, NULL);
1165 sigaction(SIGTTIN, &sa, NULL);
1166 if (interactive) {
1167 sigaddset(&blocked_set, SIGHUP);
1168 sigaddset(&blocked_set, SIGINT);
1169 sigaddset(&blocked_set, SIGQUIT);
1170 sigaddset(&blocked_set, SIGPIPE);
1171 sigaddset(&blocked_set, SIGTERM);
1172 sa.sa_handler = interrupt;
1173#ifdef SUNOS4
1174 /* POSIX signals on sunos4.1 are a little broken. */
1175 sa.sa_flags = SA_INTERRUPT;
1176#endif /* SUNOS4 */
1177 }
1178 sigaction(SIGHUP, &sa, NULL);
1179 sigaction(SIGINT, &sa, NULL);
1180 sigaction(SIGQUIT, &sa, NULL);
1181 sigaction(SIGPIPE, &sa, NULL);
1182 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001183#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184 sa.sa_handler = reaper;
1185 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001186#else
1187 /* Make sure SIGCHLD has the default action so that waitpid
1188 definitely works without losing track of children. The user
1189 should not have given us a bogus state to inherit, but he might
1190 have. Arguably we should detect SIG_IGN here and pass it on
1191 to children, but probably noone really needs that. */
1192 sa.sa_handler = SIG_DFL;
1193 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001194#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001196 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001197 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001198
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 if (trace() < 0)
1200 exit(1);
1201 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001202 fflush(NULL);
1203 if (exit_code > 0xff) {
1204 /* Child was killed by a signal, mimic that. */
1205 exit_code &= 0xff;
1206 signal(exit_code, SIG_DFL);
1207 raise(exit_code);
1208 /* Paranoia - what if this signal is not fatal?
1209 Exit with 128 + signo then. */
1210 exit_code += 128;
1211 }
1212 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213}
1214
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001215static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001216expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001217{
1218 /* Allocate some more TCBs and expand the table.
1219 We don't want to relocate the TCBs because our
1220 callers have pointers and it would be a pain.
1221 So tcbtab is a table of pointers. Since we never
1222 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001223 int i = tcbtabsize;
1224 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1225 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1226 if (newtab == NULL || newtcbs == NULL)
1227 error_msg_and_die("expand_tcbtab: out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001228 tcbtabsize *= 2;
1229 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001230 while (i < tcbtabsize)
1231 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001232}
1233
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001235alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236{
1237 int i;
1238 struct tcb *tcp;
1239
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001240 if (nprocs == tcbtabsize)
1241 expand_tcbtab();
1242
Roland McGrathee9d4352002-12-18 04:16:10 +00001243 for (i = 0; i < tcbtabsize; i++) {
1244 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001246 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248 tcp->flags = TCB_INUSE | TCB_STARTUP;
1249 tcp->outf = outf; /* Initialise to current out file */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 tcp->pfd = -1;
1251 nprocs++;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001252 if (command_options_parsed)
1253 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254 return tcp;
1255 }
1256 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001257 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001258}
1259
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001260#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001262proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263{
1264 char proc[32];
1265 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001266#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001267 int i;
1268 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 sigset_t signals;
1270 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001271#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272#ifndef HAVE_POLLABLE_PROCFS
1273 static int last_pfd;
1274#endif
1275
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001276#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001277 /* Open the process pseudo-files in /proc. */
1278 sprintf(proc, "/proc/%d/ctl", tcp->pid);
1279 if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280 perror("strace: open(\"/proc/...\", ...)");
1281 return -1;
1282 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001283 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001284 sprintf(proc, "/proc/%d/status", tcp->pid);
1285 if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
1286 perror("strace: open(\"/proc/...\", ...)");
1287 return -1;
1288 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001289 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001290 sprintf(proc, "/proc/%d/as", tcp->pid);
1291 if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
1292 perror("strace: open(\"/proc/...\", ...)");
1293 return -1;
1294 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001295 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001296#else
1297 /* Open the process pseudo-file in /proc. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001298#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001299 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001300 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001301#else /* FREEBSD */
1302 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001303 tcp->pfd = open(proc, O_RDWR);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001304#endif /* FREEBSD */
Andreas Schwab372cc842010-07-09 11:49:27 +02001305 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001306 perror("strace: open(\"/proc/...\", ...)");
1307 return -1;
1308 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001309 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001310#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001311#ifdef FREEBSD
1312 sprintf(proc, "/proc/%d/regs", tcp->pid);
1313 if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1314 perror("strace: open(\"/proc/.../regs\", ...)");
1315 return -1;
1316 }
1317 if (cflag) {
1318 sprintf(proc, "/proc/%d/status", tcp->pid);
1319 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1320 perror("strace: open(\"/proc/.../status\", ...)");
1321 return -1;
1322 }
1323 } else
1324 tcp->pfd_status = -1;
1325#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001326 rebuild_pollv();
1327 if (!attaching) {
1328 /*
1329 * Wait for the child to pause. Because of a race
1330 * condition we have to poll for the event.
1331 */
1332 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001333 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001334 perror("strace: PIOCSTATUS");
1335 return -1;
1336 }
1337 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001339 }
1340 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001341#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001342 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001343 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001344 perror("strace: PIOCSTOP");
1345 return -1;
1346 }
Roland McGrath553a6092002-12-16 20:40:39 +00001347#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001348#ifdef PIOCSET
1349 /* Set Run-on-Last-Close. */
1350 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001351 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001352 perror("PIOCSET PR_RLC");
1353 return -1;
1354 }
1355 /* Set or Reset Inherit-on-Fork. */
1356 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001357 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358 perror("PIOC{SET,RESET} PR_FORK");
1359 return -1;
1360 }
1361#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001362#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1364 perror("PIOCSRLC");
1365 return -1;
1366 }
1367 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1368 perror("PIOC{S,R}FORK");
1369 return -1;
1370 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001371#else /* FREEBSD */
1372 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1373 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1374 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001375 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001376 }
1377 arg &= ~PF_LINGER;
1378 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001379 perror("PIOCSFL");
1380 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001381 }
1382#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001383#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001384#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001385 /* Enable all syscall entries we care about. */
1386 premptyset(&syscalls);
1387 for (i = 1; i < MAX_QUALS; ++i) {
1388 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001389 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001390 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001391 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001392 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001393 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001394#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001395 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001396#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001397#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001398 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001399#endif
1400#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001401 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001402#endif
1403#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001404 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001405#endif
1406 }
1407 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001408 perror("PIOCSENTRY");
1409 return -1;
1410 }
John Hughes19e49982001-10-19 08:59:12 +00001411 /* Enable the syscall exits. */
1412 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413 perror("PIOSEXIT");
1414 return -1;
1415 }
John Hughes19e49982001-10-19 08:59:12 +00001416 /* Enable signals we care about. */
1417 premptyset(&signals);
1418 for (i = 1; i < MAX_QUALS; ++i) {
1419 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001420 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001421 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001422 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423 perror("PIOCSTRACE");
1424 return -1;
1425 }
John Hughes19e49982001-10-19 08:59:12 +00001426 /* Enable faults we care about */
1427 premptyset(&faults);
1428 for (i = 1; i < MAX_QUALS; ++i) {
1429 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001430 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001431 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001432 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433 perror("PIOCSFAULT");
1434 return -1;
1435 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001436#else /* FREEBSD */
1437 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001438 arg = S_SIG | S_SCE | S_SCX;
1439 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001440 perror("PIOCBIS");
1441 return -1;
1442 }
1443#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 if (!attaching) {
1445#ifdef MIPS
1446 /*
1447 * The SGI PRSABORT doesn't work for pause() so
1448 * we send it a caught signal to wake it up.
1449 */
1450 kill(tcp->pid, SIGINT);
1451#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001452#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001454 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001455 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456 perror("PIOCRUN");
1457 return -1;
1458 }
Roland McGrath553a6092002-12-16 20:40:39 +00001459#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001460#endif /* !MIPS*/
1461#ifdef FREEBSD
1462 /* wake up the child if it received the SIGSTOP */
1463 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001464#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001465 for (;;) {
1466 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001467 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468 perror("PIOCWSTOP");
1469 return -1;
1470 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001471 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001472 tcp->flags &= ~TCB_INSYSCALL;
1473 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001474 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475 break;
1476 }
1477 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001478#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001479 arg = 0;
1480 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001481#else /* FREEBSD */
1482 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
Roland McGrath553a6092002-12-16 20:40:39 +00001483#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484 perror("PIOCRUN");
1485 return -1;
1486 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001487#ifdef FREEBSD
1488 /* handle the case where we "opened" the child before
1489 it did the kill -STOP */
1490 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1491 tcp->status.PR_WHAT == SIGSTOP)
1492 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001493#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001495#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001497#else /* FREEBSD */
1498 } else {
Roland McGrath553a6092002-12-16 20:40:39 +00001499 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001500 /* We are attaching to an already running process.
1501 * Try to figure out the state of the process in syscalls,
1502 * to handle the first event well.
1503 * This is done by having a look at the "wchan" property of the
1504 * process, which tells where it is stopped (if it is). */
1505 FILE * status;
1506 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001507
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001508 sprintf(proc, "/proc/%d/status", tcp->pid);
1509 status = fopen(proc, "r");
1510 if (status &&
1511 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1512 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1513 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1514 strcmp(wchan, "stopevent")) {
1515 /* The process is asleep in the middle of a syscall.
1516 Fake the syscall entry event */
1517 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1518 tcp->status.PR_WHY = PR_SYSENTRY;
1519 trace_syscall(tcp);
1520 }
1521 if (status)
1522 fclose(status);
1523 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001524 }
1525#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526#ifndef HAVE_POLLABLE_PROCFS
1527 if (proc_poll_pipe[0] != -1)
1528 proc_poller(tcp->pfd);
1529 else if (nprocs > 1) {
1530 proc_poll_open();
1531 proc_poller(last_pfd);
1532 proc_poller(tcp->pfd);
1533 }
1534 last_pfd = tcp->pfd;
1535#endif /* !HAVE_POLLABLE_PROCFS */
1536 return 0;
1537}
1538
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001539#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001541struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001542pid2tcb(int pid)
1543{
1544 int i;
1545
1546 if (pid <= 0)
1547 return NULL;
1548
1549 for (i = 0; i < tcbtabsize; i++) {
1550 struct tcb *tcp = tcbtab[i];
1551 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1552 return tcp;
1553 }
1554
1555 return NULL;
1556}
1557
1558#ifdef USE_PROCFS
1559
1560static struct tcb *
1561first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562{
1563 int i;
1564 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001565 for (i = 0; i < tcbtabsize; i++) {
1566 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567 if (tcp->flags & TCB_INUSE)
1568 return tcp;
1569 }
1570 return NULL;
1571}
1572
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001574pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575{
1576 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577
Roland McGrathca16be82003-01-10 19:55:28 +00001578 for (i = 0; i < tcbtabsize; i++) {
1579 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580 if (tcp->pfd != pfd)
1581 continue;
1582 if (tcp->flags & TCB_INUSE)
1583 return tcp;
1584 }
1585 return NULL;
1586}
1587
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001588#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589
1590void
Denys Vlasenko12014262011-05-30 14:00:14 +02001591droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592{
1593 if (tcp->pid == 0)
1594 return;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001595#ifdef TCB_CLONE_THREAD
1596 if (tcp->nclone_threads > 0) {
1597 /* There are other threads left in this process, but this
1598 is the one whose PID represents the whole process.
1599 We need to keep this record around as a zombie until
1600 all the threads die. */
1601 tcp->flags |= TCB_EXITING;
1602 return;
1603 }
1604#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605 nprocs--;
1606 tcp->pid = 0;
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001607
Roland McGrathe29341c2003-01-10 20:14:20 +00001608 if (tcp->parent != NULL) {
Roland McGrathe29341c2003-01-10 20:14:20 +00001609#ifdef TCB_CLONE_THREAD
Roland McGrathe29341c2003-01-10 20:14:20 +00001610 if (tcp->flags & TCB_CLONE_THREAD)
1611 tcp->parent->nclone_threads--;
1612#endif
Roland McGrath276ceb32007-11-13 08:12:12 +00001613#ifdef LINUX
Denys Vlasenkob56d6d32011-06-21 16:06:28 +02001614 /* Update fields like NCLONE_DETACHED, only
1615 for zombie group leader that has already reported
1616 and been short-circuited at the top of this
Roland McGrath276ceb32007-11-13 08:12:12 +00001617 function. The same condition as at the top of DETACH. */
1618 if ((tcp->flags & TCB_CLONE_THREAD) &&
1619 tcp->parent->nclone_threads == 0 &&
1620 (tcp->parent->flags & TCB_EXITING))
1621 droptcb(tcp->parent);
1622#endif
Roland McGrathe29341c2003-01-10 20:14:20 +00001623 tcp->parent = NULL;
1624 }
1625
1626 tcp->flags = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 if (tcp->pfd != -1) {
1628 close(tcp->pfd);
1629 tcp->pfd = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001630#ifdef FREEBSD
1631 if (tcp->pfd_reg != -1) {
1632 close(tcp->pfd_reg);
1633 tcp->pfd_reg = -1;
1634 }
1635 if (tcp->pfd_status != -1) {
1636 close(tcp->pfd_status);
1637 tcp->pfd_status = -1;
1638 }
Roland McGrath553a6092002-12-16 20:40:39 +00001639#endif /* !FREEBSD */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001640#ifdef USE_PROCFS
Roland McGrathe29341c2003-01-10 20:14:20 +00001641 rebuild_pollv(); /* Note, flags needs to be cleared by now. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642#endif
1643 }
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001644
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001645 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001647
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 tcp->outf = 0;
1649}
1650
Roland McGrath0a463882007-07-05 18:43:16 +00001651/* detach traced process; continue with sig
1652 Never call DETACH twice on the same process as both unattached and
1653 attached-unstopped processes give the same ESRCH. For unattached process we
1654 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655
1656static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001657detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658{
1659 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001660#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001661 int status, catch_sigstop;
Roland McGratha08a97e2005-08-03 11:23:46 +00001662 struct tcb *zombie = NULL;
1663
1664 /* If the group leader is lingering only because of this other
1665 thread now dying, then detach the leader as well. */
1666 if ((tcp->flags & TCB_CLONE_THREAD) &&
1667 tcp->parent->nclone_threads == 1 &&
1668 (tcp->parent->flags & TCB_EXITING))
1669 zombie = tcp->parent;
Roland McGrathca16be82003-01-10 19:55:28 +00001670#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671
1672 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001673 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674
1675#ifdef LINUX
1676 /*
1677 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001678 * before detaching. Arghh. We go through hoops
1679 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001681#if defined(SPARC)
1682#undef PTRACE_DETACH
1683#define PTRACE_DETACH PTRACE_SUNDETACH
1684#endif
Roland McGrath02203312007-06-11 22:06:31 +00001685 /*
1686 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1687 * expected SIGSTOP. We must catch exactly one as otherwise the
1688 * detached process would be left stopped (process state T).
1689 */
1690 catch_sigstop = (tcp->flags & TCB_STARTUP);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
1692 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001693 }
1694 else if (errno != ESRCH) {
1695 /* Shouldn't happen. */
1696 perror("detach: ptrace(PTRACE_DETACH, ...)");
1697 }
Roland McGrath134813a2007-06-02 00:07:33 +00001698 else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1699 : tcp->pid),
1700 tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001701 if (errno != ESRCH)
1702 perror("detach: checking sanity");
1703 }
Roland McGrath02203312007-06-11 22:06:31 +00001704 else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
1705 ? tcp->parent->pid : tcp->pid),
1706 tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001707 if (errno != ESRCH)
1708 perror("detach: stopping child");
1709 }
Roland McGrath02203312007-06-11 22:06:31 +00001710 else
1711 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001712 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001714#ifdef __WALL
1715 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1716 if (errno == ECHILD) /* Already gone. */
1717 break;
1718 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001719 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001720 break;
1721 }
1722#endif /* __WALL */
1723 /* No __WALL here. */
1724 if (waitpid(tcp->pid, &status, 0) < 0) {
1725 if (errno != ECHILD) {
1726 perror("detach: waiting");
1727 break;
1728 }
1729#ifdef __WCLONE
1730 /* If no processes, try clones. */
1731 if (wait4(tcp->pid, &status, __WCLONE,
1732 NULL) < 0) {
1733 if (errno != ECHILD)
1734 perror("detach: waiting");
1735 break;
1736 }
1737#endif /* __WCLONE */
1738 }
1739#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001740 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001741#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001742 if (!WIFSTOPPED(status)) {
1743 /* Au revoir, mon ami. */
1744 break;
1745 }
1746 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001747 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748 break;
1749 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001750 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001751 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001752 : WSTOPSIG(status));
1753 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001756 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001757#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758
1759#if defined(SUNOS4)
1760 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1761 if (sig && kill(tcp->pid, sig) < 0)
1762 perror("detach: kill");
1763 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001764 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765#endif /* SUNOS4 */
1766
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 if (!qflag)
1768 fprintf(stderr, "Process %u detached\n", tcp->pid);
1769
1770 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001771
1772#ifdef LINUX
Roland McGrath0a463882007-07-05 18:43:16 +00001773 if (zombie != NULL) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001774 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00001775 droptcb(zombie);
1776 }
Roland McGratha08a97e2005-08-03 11:23:46 +00001777#endif
1778
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779 return error;
1780}
1781
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001782#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001784static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785{
1786 int pid;
1787 int status;
1788
1789 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 }
1791}
1792
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001793#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794
1795static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001796cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797{
1798 int i;
1799 struct tcb *tcp;
1800
Roland McGrathee9d4352002-12-18 04:16:10 +00001801 for (i = 0; i < tcbtabsize; i++) {
1802 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803 if (!(tcp->flags & TCB_INUSE))
1804 continue;
1805 if (debug)
1806 fprintf(stderr,
1807 "cleanup: looking at pid %u\n", tcp->pid);
1808 if (tcp_last &&
1809 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001810 tprintf(" <unfinished ...>");
1811 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812 }
1813 if (tcp->flags & TCB_ATTACHED)
1814 detach(tcp, 0);
1815 else {
1816 kill(tcp->pid, SIGCONT);
1817 kill(tcp->pid, SIGTERM);
1818 }
1819 }
1820 if (cflag)
1821 call_summary(outf);
1822}
1823
1824static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001825interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826{
1827 interrupted = 1;
1828}
1829
1830#ifndef HAVE_STRERROR
1831
Roland McGrath6d2b3492002-12-30 00:51:30 +00001832#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833extern int sys_nerr;
1834extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001835#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836
1837const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001838strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001839{
1840 static char buf[64];
1841
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001842 if (err_no < 1 || err_no >= sys_nerr) {
1843 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844 return buf;
1845 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001846 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847}
1848
1849#endif /* HAVE_STERRROR */
1850
1851#ifndef HAVE_STRSIGNAL
1852
Roland McGrath8f474e02003-01-14 07:53:33 +00001853#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001854extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001855#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001856#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1857extern char *_sys_siglist[];
1858#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001859
1860const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001861strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862{
1863 static char buf[64];
1864
1865 if (sig < 1 || sig >= NSIG) {
1866 sprintf(buf, "Unknown signal %d", sig);
1867 return buf;
1868 }
1869#ifdef HAVE__SYS_SIGLIST
1870 return _sys_siglist[sig];
1871#else
1872 return sys_siglist[sig];
1873#endif
1874}
1875
1876#endif /* HAVE_STRSIGNAL */
1877
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001878#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879
1880static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001881rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882{
1883 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884
Roland McGrathee9d4352002-12-18 04:16:10 +00001885 if (pollv != NULL)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001886 free(pollv);
Roland McGrathc012d222003-01-10 20:05:56 +00001887 pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
Roland McGrathee9d4352002-12-18 04:16:10 +00001888 if (pollv == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00001889 fprintf(stderr, "%s: out of memory\n", progname);
Roland McGrathee9d4352002-12-18 04:16:10 +00001890 exit(1);
1891 }
1892
Roland McGrathca16be82003-01-10 19:55:28 +00001893 for (i = j = 0; i < tcbtabsize; i++) {
1894 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001895 if (!(tcp->flags & TCB_INUSE))
1896 continue;
1897 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001898 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 j++;
1900 }
1901 if (j != nprocs) {
1902 fprintf(stderr, "strace: proc miscount\n");
1903 exit(1);
1904 }
1905}
1906
1907#ifndef HAVE_POLLABLE_PROCFS
1908
1909static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001910proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912 int i;
1913
1914 if (pipe(proc_poll_pipe) < 0) {
1915 perror("pipe");
1916 exit(1);
1917 }
1918 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001919 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001920 }
1921}
1922
1923static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001924proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001925{
1926 int i;
1927 int n;
1928 struct proc_pollfd pollinfo;
1929
1930 if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1931 return n;
1932 if (n != sizeof(struct proc_pollfd)) {
1933 fprintf(stderr, "panic: short read: %d\n", n);
1934 exit(1);
1935 }
1936 for (i = 0; i < nprocs; i++) {
1937 if (pollv[i].fd == pollinfo.fd)
1938 pollv[i].revents = pollinfo.revents;
1939 else
1940 pollv[i].revents = 0;
1941 }
1942 poller_pid = pollinfo.pid;
1943 return 1;
1944}
1945
1946static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001947wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948{
1949}
1950
1951static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001952proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953{
1954 struct proc_pollfd pollinfo;
1955 struct sigaction sa;
1956 sigset_t blocked_set, empty_set;
1957 int i;
1958 int n;
1959 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001960#ifdef FREEBSD
1961 struct procfs_status pfs;
1962#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001963
1964 switch (fork()) {
1965 case -1:
1966 perror("fork");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001967 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001968 case 0:
1969 break;
1970 default:
1971 return;
1972 }
1973
1974 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1975 sa.sa_flags = 0;
1976 sigemptyset(&sa.sa_mask);
1977 sigaction(SIGHUP, &sa, NULL);
1978 sigaction(SIGINT, &sa, NULL);
1979 sigaction(SIGQUIT, &sa, NULL);
1980 sigaction(SIGPIPE, &sa, NULL);
1981 sigaction(SIGTERM, &sa, NULL);
1982 sa.sa_handler = wakeup_handler;
1983 sigaction(SIGUSR1, &sa, NULL);
1984 sigemptyset(&blocked_set);
1985 sigaddset(&blocked_set, SIGUSR1);
1986 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1987 sigemptyset(&empty_set);
1988
1989 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1990 perror("getrlimit(RLIMIT_NOFILE, ...)");
Dmitry V. Levina6809652008-11-10 17:14:58 +00001991 _exit(1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001992 }
1993 n = rl.rlim_cur;
1994 for (i = 0; i < n; i++) {
1995 if (i != pfd && i != proc_poll_pipe[1])
1996 close(i);
1997 }
1998
1999 pollinfo.fd = pfd;
2000 pollinfo.pid = getpid();
2001 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002002#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002003 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2004#else
2005 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2006#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002007 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002008 switch (errno) {
2009 case EINTR:
2010 continue;
2011 case EBADF:
2012 pollinfo.revents = POLLERR;
2013 break;
2014 case ENOENT:
2015 pollinfo.revents = POLLHUP;
2016 break;
2017 default:
2018 perror("proc_poller: PIOCWSTOP");
2019 }
2020 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2021 _exit(0);
2022 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002023 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2025 sigsuspend(&empty_set);
2026 }
2027}
2028
2029#endif /* !HAVE_POLLABLE_PROCFS */
2030
2031static int
2032choose_pfd()
2033{
2034 int i, j;
2035 struct tcb *tcp;
2036
2037 static int last;
2038
2039 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002040 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041 /*
2042 * The previous process is ready to run again. We'll
2043 * let it do so if it is currently in a syscall. This
2044 * heuristic improves the readability of the trace.
2045 */
2046 tcp = pfd2tcb(pollv[last].fd);
2047 if (tcp && (tcp->flags & TCB_INSYSCALL))
2048 return pollv[last].fd;
2049 }
2050
2051 for (i = 0; i < nprocs; i++) {
2052 /* Let competing children run round robin. */
2053 j = (i + last + 1) % nprocs;
2054 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2055 tcp = pfd2tcb(pollv[j].fd);
2056 if (!tcp) {
2057 fprintf(stderr, "strace: lost proc\n");
2058 exit(1);
2059 }
2060 droptcb(tcp);
2061 return -1;
2062 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002063 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002064 last = j;
2065 return pollv[j].fd;
2066 }
2067 }
2068 fprintf(stderr, "strace: nothing ready\n");
2069 exit(1);
2070}
2071
2072static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002073trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002074{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002075#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002076 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002077#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 struct tcb *tcp;
2079 int pfd;
2080 int what;
2081 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002082 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083
2084 for (;;) {
2085 if (interactive)
2086 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2087
2088 if (nprocs == 0)
2089 break;
2090
2091 switch (nprocs) {
2092 case 1:
2093#ifndef HAVE_POLLABLE_PROCFS
2094 if (proc_poll_pipe[0] == -1) {
2095#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002096 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002097 if (!tcp)
2098 continue;
2099 pfd = tcp->pfd;
2100 if (pfd == -1)
2101 continue;
2102 break;
2103#ifndef HAVE_POLLABLE_PROCFS
2104 }
2105 /* fall through ... */
2106#endif /* !HAVE_POLLABLE_PROCFS */
2107 default:
2108#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002109#ifdef POLL_HACK
2110 /* On some systems (e.g. UnixWare) we get too much ugly
2111 "unfinished..." stuff when multiple proceses are in
2112 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002113
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002114 if (in_syscall) {
2115 struct pollfd pv;
2116 tcp = in_syscall;
2117 in_syscall = NULL;
2118 pv.fd = tcp->pfd;
2119 pv.events = POLLWANT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002120 if ((what = poll(&pv, 1, 1)) < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002121 if (interrupted)
2122 return 0;
2123 continue;
2124 }
2125 else if (what == 1 && pv.revents & POLLWANT) {
2126 goto FOUND;
2127 }
2128 }
2129#endif
2130
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002131 if (poll(pollv, nprocs, INFTIM) < 0) {
2132 if (interrupted)
2133 return 0;
2134 continue;
2135 }
2136#else /* !HAVE_POLLABLE_PROCFS */
2137 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2138 if (interrupted)
2139 return 0;
2140 continue;
2141 }
2142#endif /* !HAVE_POLLABLE_PROCFS */
2143 pfd = choose_pfd();
2144 if (pfd == -1)
2145 continue;
2146 break;
2147 }
2148
2149 /* Look up `pfd' in our table. */
2150 if ((tcp = pfd2tcb(pfd)) == NULL) {
2151 fprintf(stderr, "unknown pfd: %u\n", pfd);
2152 exit(1);
2153 }
John Hughesb6643082002-05-23 11:02:22 +00002154#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002155 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002156#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002157 /* Get the status of the process. */
2158 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002159#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002160 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002161#else /* FREEBSD */
2162 /* Thanks to some scheduling mystery, the first poller
2163 sometimes waits for the already processed end of fork
2164 event. Doing a non blocking poll here solves the problem. */
2165 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002166 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002167 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002168 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002169#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 ioctl_errno = errno;
2171#ifndef HAVE_POLLABLE_PROCFS
2172 if (proc_poll_pipe[0] != -1) {
2173 if (ioctl_result < 0)
2174 kill(poller_pid, SIGKILL);
2175 else
2176 kill(poller_pid, SIGUSR1);
2177 }
2178#endif /* !HAVE_POLLABLE_PROCFS */
2179 }
2180 if (interrupted)
2181 return 0;
2182
2183 if (interactive)
2184 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2185
2186 if (ioctl_result < 0) {
2187 /* Find out what happened if it failed. */
2188 switch (ioctl_errno) {
2189 case EINTR:
2190 case EBADF:
2191 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002192#ifdef FREEBSD
2193 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002194#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002195 case ENOENT:
2196 droptcb(tcp);
2197 continue;
2198 default:
2199 perror("PIOCWSTOP");
2200 exit(1);
2201 }
2202 }
2203
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002204#ifdef FREEBSD
2205 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2206 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002207 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002208 continue;
2209 }
Roland McGrath553a6092002-12-16 20:40:39 +00002210#endif
2211
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 /* clear the just started flag */
2213 tcp->flags &= ~TCB_STARTUP;
2214
2215 /* set current output file */
2216 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002217 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218
2219 if (cflag) {
2220 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002221#ifdef FREEBSD
2222 char buf[1024];
2223 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002224
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002225 if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2226 buf[len] = '\0';
2227 sscanf(buf,
2228 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2229 &stime.tv_sec, &stime.tv_usec);
2230 } else
2231 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002232#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2234 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002235#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002236 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2237 tcp->stime = stime;
2238 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002239 what = tcp->status.PR_WHAT;
2240 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002241#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002242 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002243 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2244 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245 if (trace_syscall(tcp) < 0) {
2246 fprintf(stderr, "syscall trouble\n");
2247 exit(1);
2248 }
2249 }
2250 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002251#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002252 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002253#ifdef POLL_HACK
2254 in_syscall = tcp;
2255#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 case PR_SYSEXIT:
2257 if (trace_syscall(tcp) < 0) {
2258 fprintf(stderr, "syscall trouble\n");
2259 exit(1);
2260 }
2261 break;
2262 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002263 if (cflag != CFLAG_ONLY_STATS
2264 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 printleader(tcp);
2266 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002267 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002268 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002269#ifdef PR_INFO
2270 if (tcp->status.PR_INFO.si_signo == what) {
2271 printleader(tcp);
2272 tprintf(" siginfo=");
2273 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002274 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002275 }
2276#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277 }
2278 break;
2279 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002280 if (cflag != CFLAGS_ONLY_STATS
2281 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002282 printleader(tcp);
2283 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002284 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285 }
2286 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002287#ifdef FREEBSD
2288 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002289 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002290#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002291 default:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002292 fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002293 exit(1);
2294 break;
2295 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002296 /* Remember current print column before continuing. */
2297 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002298 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002299#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002300 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002301#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002302 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002303#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002304 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 perror("PIOCRUN");
2306 exit(1);
2307 }
2308 }
2309 return 0;
2310}
2311
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002312#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002313
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002314#ifdef TCB_GROUP_EXITING
2315/* Handle an exit detach or death signal that is taking all the
2316 related clone threads with it. This is called in three circumstances:
2317 SIG == -1 TCP has already died (TCB_ATTACHED is clear, strace is parent).
2318 SIG == 0 Continuing TCP will perform an exit_group syscall.
2319 SIG == other Continuing TCP with SIG will kill the process.
2320*/
2321static int
2322handle_group_exit(struct tcb *tcp, int sig)
2323{
2324 /* We need to locate our records of all the clone threads
2325 related to TCP, either its children or siblings. */
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002326 struct tcb *leader = NULL;
2327
2328 if (tcp->flags & TCB_CLONE_THREAD)
2329 leader = tcp->parent;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002330
2331 if (sig < 0) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002332 if (leader != NULL && leader != tcp
2333 && !(leader->flags & TCB_GROUP_EXITING)
2334 && !(tcp->flags & TCB_STARTUP)
2335 ) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002336 fprintf(stderr,
2337 "PANIC: handle_group_exit: %d leader %d\n",
2338 tcp->pid, leader ? leader->pid : -1);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002339 }
2340 /* TCP no longer exists therefore you must not detach() it. */
Roland McGrath0a463882007-07-05 18:43:16 +00002341 droptcb(tcp); /* Already died. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002342 }
2343 else {
Roland McGratha08a97e2005-08-03 11:23:46 +00002344 /* Mark that we are taking the process down. */
2345 tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002346 if (tcp->flags & TCB_ATTACHED) {
Roland McGrathd6a32f12007-07-11 08:35:11 +00002347 detach(tcp, sig);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002348 if (leader != NULL && leader != tcp)
Roland McGrath1bfd3102007-08-03 10:02:00 +00002349 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002350 } else {
2351 if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2352 cleanup();
2353 return -1;
2354 }
2355 if (leader != NULL) {
Roland McGrath05690952004-10-20 01:00:27 +00002356 leader->flags |= TCB_GROUP_EXITING;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002357 if (leader != tcp)
2358 droptcb(tcp);
2359 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002360 /* The leader will report to us as parent now,
2361 and then we'll get to the SIG==-1 case. */
2362 return 0;
2363 }
2364 }
2365
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002366 return 0;
2367}
2368#endif
2369
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002370#ifdef LINUX
2371static int
2372handle_ptrace_event(int status, struct tcb *tcp)
2373{
2374 if (status >> 16 == PTRACE_EVENT_VFORK ||
2375 status >> 16 == PTRACE_EVENT_CLONE ||
2376 status >> 16 == PTRACE_EVENT_FORK) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +00002377 long childpid;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002378
2379 if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2380 if (errno != ESRCH) {
2381 fprintf(stderr, "\
2382%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2383 progname);
2384 cleanup();
2385 exit(1);
2386 }
2387 return -1;
2388 }
2389 return handle_new_child(tcp, childpid, 0);
2390 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002391 if (status >> 16 == PTRACE_EVENT_EXEC) {
2392 if (debug)
2393 fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
2394 return 0;
2395 }
Denys Vlasenko75422762011-05-27 14:36:01 +02002396 /* Some PTRACE_EVENT_foo we didn't ask for?! */
2397 error_msg("Unexpected status %x on pid %d", status, tcp->pid);
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002398 return 1;
2399}
2400#endif
2401
Roland McGratheb9e2e82009-06-02 16:49:22 -07002402static int
2403trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002404{
2405 int pid;
2406 int wait_errno;
2407 int status;
2408 struct tcb *tcp;
2409#ifdef LINUX
2410 struct rusage ru;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002411#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002412 static int wait4_options = __WALL;
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002413#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002414#endif /* LINUX */
2415
Roland McGratheb9e2e82009-06-02 16:49:22 -07002416 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002417 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002418 return 0;
2419 if (interactive)
2420 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002421#ifdef LINUX
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002422#ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002423 pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
Roland McGrath5bc05552002-12-17 04:50:47 +00002424 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002425 /* this kernel does not support __WALL */
2426 wait4_options &= ~__WALL;
2427 errno = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002428 pid = wait4(-1, &status, wait4_options,
2429 cflag ? &ru : NULL);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002430 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002431 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002432 /* most likely a "cloned" process */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002433 pid = wait4(-1, &status, __WCLONE,
2434 cflag ? &ru : NULL);
2435 if (pid == -1) {
2436 fprintf(stderr, "strace: clone wait4 "
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002437 "failed: %s\n", strerror(errno));
2438 }
2439 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002440#else
2441 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2442#endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443#endif /* LINUX */
2444#ifdef SUNOS4
2445 pid = wait(&status);
2446#endif /* SUNOS4 */
2447 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002448 if (interactive)
2449 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002450
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002451 if (pid == -1) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002452 switch (wait_errno) {
2453 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002455 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456 /*
2457 * We would like to verify this case
2458 * but sometimes a race in Solbourne's
2459 * version of SunOS sometimes reports
2460 * ECHILD before sending us SIGCHILD.
2461 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002462 return 0;
2463 default:
2464 errno = wait_errno;
2465 perror("strace: wait");
2466 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002467 }
2468 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002469 if (pid == popen_pid) {
2470 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002471 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002472 continue;
2473 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002474 if (debug)
2475 fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
2476
2477 /* Look up `pid' in our table. */
2478 if ((tcp = pid2tcb(pid)) == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002479#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002480 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002481 /* This is needed to go with the CLONE_PTRACE
2482 changes in process.c/util.c: we might see
2483 the child's initial trap before we see the
2484 parent return from the clone syscall.
2485 Leave the child suspended until the parent
2486 returns from its system call. Only then
2487 will we have the association of parent and
2488 child so that we know how to do clearbpt
2489 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002490 tcp = alloctcb(pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002491 tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002492 if (!qflag)
2493 fprintf(stderr, "\
2494Process %d attached (waiting for parent)\n",
2495 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002496 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002497 else
2498 /* This can happen if a clone call used
2499 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002500#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002501 {
2502 fprintf(stderr, "unknown pid: %u\n", pid);
2503 if (WIFSTOPPED(status))
2504 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2505 exit(1);
2506 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002507 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002508 /* set current output file */
2509 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002510 curcol = tcp->curcol;
Denys Vlasenko84e20af2009-02-10 16:03:20 +00002511 if (cflag) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002512#ifdef LINUX
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002513 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2514 tcp->stime = ru.ru_stime;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002515#endif /* !LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002516 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002517
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002518 if (tcp->flags & TCB_SUSPENDED) {
2519 /*
2520 * Apparently, doing any ptrace() call on a stopped
2521 * process, provokes the kernel to report the process
2522 * status again on a subsequent wait(), even if the
2523 * process has not been actually restarted.
2524 * Since we have inspected the arguments of suspended
2525 * processes we end up here testing for this case.
2526 */
2527 continue;
2528 }
2529 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002530 if (pid == strace_child)
2531 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002532 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002533 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2534 printleader(tcp);
Roland McGrath2efe8792004-01-13 09:59:45 +00002535 tprintf("+++ killed by %s %s+++",
2536 signame(WTERMSIG(status)),
2537#ifdef WCOREDUMP
2538 WCOREDUMP(status) ? "(core dumped) " :
2539#endif
2540 "");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002541 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002542 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002543#ifdef TCB_GROUP_EXITING
2544 handle_group_exit(tcp, -1);
2545#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002547#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002548 continue;
2549 }
2550 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002551 if (pid == strace_child)
2552 exit_code = WEXITSTATUS(status);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553 if (debug)
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002554 fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
2555 if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
Roland McGrath05690952004-10-20 01:00:27 +00002556#ifdef TCB_GROUP_EXITING
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002557 && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
Roland McGrath1bfd3102007-08-03 10:02:00 +00002558 && !(tcp->flags & TCB_GROUP_EXITING)
Roland McGrath05690952004-10-20 01:00:27 +00002559#endif
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002560 ) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002561 fprintf(stderr,
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002562 "PANIC: attached pid %u exited with %d\n",
2563 pid, WEXITSTATUS(status));
2564 }
Roland McGrath0a396902003-06-10 03:05:53 +00002565 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002566 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002567 tprintf(" <unfinished ... exit status %d>\n",
2568 WEXITSTATUS(status));
2569 tcp_last = NULL;
2570 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002571#ifdef TCB_GROUP_EXITING
2572 handle_group_exit(tcp, -1);
2573#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002574 droptcb(tcp);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002575#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002576 continue;
2577 }
2578 if (!WIFSTOPPED(status)) {
2579 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2580 droptcb(tcp);
2581 continue;
2582 }
2583 if (debug)
2584 fprintf(stderr, "pid %u stopped, [%s]\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002585 pid, signame(WSTOPSIG(status)));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002586
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002587 if (status >> 16) {
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002588 if (handle_ptrace_event(status, tcp) != 1)
2589 goto tracing;
2590 }
2591
Roland McGrath02203312007-06-11 22:06:31 +00002592 /*
2593 * Interestingly, the process may stop
2594 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002595 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002596 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002597 * A no-MMU vforked child won't send up a signal,
2598 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002599 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002600 if ((tcp->flags & TCB_STARTUP) &&
2601 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002602 /*
2603 * This flag is there to keep us in sync.
2604 * Next time this process stops it should
2605 * really be entering a system call.
2606 */
2607 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002608 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002609 /*
2610 * One example is a breakpoint inherited from
2611 * parent through fork ().
2612 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2614 droptcb(tcp);
2615 cleanup();
2616 return -1;
2617 }
2618 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002619#ifdef LINUX
Denys Vlasenkof44cce42011-06-21 14:34:10 +02002620 /* If options were not set for this tracee yet */
2621 if (tcp->parent == NULL) {
2622 if (ptrace_setoptions) {
2623 if (debug)
2624 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2625 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2626 if (errno != ESRCH) {
2627 /* Should never happen, really */
2628 perror_msg_and_die("PTRACE_SETOPTIONS");
2629 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002630 }
2631 }
2632 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002633#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002634 goto tracing;
2635 }
2636
Denys Vlasenko75422762011-05-27 14:36:01 +02002637 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002638 if (WSTOPSIG(status) == SIGSTOP &&
2639 (tcp->flags & TCB_SIGTRAPPED)) {
2640 /*
2641 * Trapped attempt to block SIGTRAP
2642 * Hope we are back in control now.
2643 */
2644 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002645 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002646 cleanup();
2647 return -1;
2648 }
2649 continue;
2650 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002651 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002652 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002653 siginfo_t si;
2654#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002655 long pc = 0;
2656 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002657
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002658 upeek(tcp, PT_CR_IPSR, &psr);
2659 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002660
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002661# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002662 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002663# define PC_FORMAT_STR " @ %lx"
2664# define PC_FORMAT_ARG pc
2665#else
2666# define PC_FORMAT_STR "%s"
2667# define PC_FORMAT_ARG ""
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002668#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002669 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002670 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2671 tprintf("--- ");
2672 printsiginfo(&si, verbose(tcp));
2673 tprintf(" (%s)" PC_FORMAT_STR " ---",
2674 strsignal(WSTOPSIG(status)),
2675 PC_FORMAT_ARG);
2676 } else
2677 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2678 strsignal(WSTOPSIG(status)),
2679 signame(WSTOPSIG(status)),
2680 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002681 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002682 }
Roland McGrath05690952004-10-20 01:00:27 +00002683 if (((tcp->flags & TCB_ATTACHED) ||
2684 tcp->nclone_threads > 0) &&
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002685 !sigishandled(tcp, WSTOPSIG(status))) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002686#ifdef TCB_GROUP_EXITING
2687 handle_group_exit(tcp, WSTOPSIG(status));
2688#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002689 detach(tcp, WSTOPSIG(status));
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002690#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002691 continue;
2692 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002693 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694 cleanup();
2695 return -1;
2696 }
2697 tcp->flags &= ~TCB_SUSPENDED;
2698 continue;
2699 }
Roland McGrath02203312007-06-11 22:06:31 +00002700 /* we handled the STATUS, we are permitted to interrupt now. */
2701 if (interrupted)
2702 return 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002703 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2704 /* ptrace() failed in trace_syscall() with ESRCH.
2705 * Likely a result of process disappearing mid-flight.
2706 * Observed case: exit_group() terminating
2707 * all processes in thread group. In this case, threads
2708 * "disappear" in an unpredictable moment without any
2709 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002710 */
2711 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002712 if (tcp_last) {
2713 /* Do we have dangling line "syscall(param, param"?
2714 * Finish the line then. We cannot
2715 */
2716 tcp_last->flags |= TCB_REPRINT;
2717 tprintf(" <unfinished ...>");
2718 printtrailer();
2719 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002720 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002721 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002722 ptrace(PTRACE_KILL,
2723 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002724 droptcb(tcp);
2725 }
2726 continue;
2727 }
2728 if (tcp->flags & TCB_EXITING) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002729#ifdef TCB_GROUP_EXITING
2730 if (tcp->flags & TCB_GROUP_EXITING) {
2731 if (handle_group_exit(tcp, 0) < 0)
2732 return -1;
2733 continue;
2734 }
2735#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002736 if (tcp->flags & TCB_ATTACHED)
2737 detach(tcp, 0);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002738 else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002739 cleanup();
2740 return -1;
2741 }
2742 continue;
2743 }
2744 if (tcp->flags & TCB_SUSPENDED) {
2745 if (!qflag)
2746 fprintf(stderr, "Process %u suspended\n", pid);
2747 continue;
2748 }
2749 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002750 /* Remember current print column before continuing. */
2751 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002752 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002753 cleanup();
2754 return -1;
2755 }
2756 }
2757 return 0;
2758}
2759
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002760#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002761
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002762#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002763
2764void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002765tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002766{
2767 va_list args;
2768
Andreas Schwabe5355de2009-10-27 16:56:43 +01002769 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002770 if (outf) {
2771 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002772 if (n < 0) {
2773 if (outf != stderr)
2774 perror(outfname == NULL
2775 ? "<writing to pipe>" : outfname);
2776 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002777 curcol += n;
2778 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002779 va_end(args);
2780 return;
2781}
2782
2783void
Denys Vlasenko12014262011-05-30 14:00:14 +02002784printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002785{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002786 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002787 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002788 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002789 tprintf(" <unavailable>) ");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002790 tabto(acolumn);
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002791 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002792 tprintf("= ? <unavailable>\n");
2793 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002794 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002795 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002796 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002797 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002798 }
2799 curcol = 0;
2800 if ((followfork == 1 || pflag_seen > 1) && outfname)
2801 tprintf("%-5d ", tcp->pid);
2802 else if (nprocs > 1 && !outfname)
2803 tprintf("[pid %5u] ", tcp->pid);
2804 if (tflag) {
2805 char str[sizeof("HH:MM:SS")];
2806 struct timeval tv, dtv;
2807 static struct timeval otv;
2808
2809 gettimeofday(&tv, NULL);
2810 if (rflag) {
2811 if (otv.tv_sec == 0)
2812 otv = tv;
2813 tv_sub(&dtv, &tv, &otv);
2814 tprintf("%6ld.%06ld ",
2815 (long) dtv.tv_sec, (long) dtv.tv_usec);
2816 otv = tv;
2817 }
2818 else if (tflag > 2) {
2819 tprintf("%ld.%06ld ",
2820 (long) tv.tv_sec, (long) tv.tv_usec);
2821 }
2822 else {
2823 time_t local = tv.tv_sec;
2824 strftime(str, sizeof(str), "%T", localtime(&local));
2825 if (tflag > 1)
2826 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2827 else
2828 tprintf("%s ", str);
2829 }
2830 }
2831 if (iflag)
2832 printcall(tcp);
2833}
2834
2835void
Denys Vlasenko12014262011-05-30 14:00:14 +02002836tabto(int col)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002837{
2838 if (curcol < col)
2839 tprintf("%*s", col - curcol, "");
2840}
2841
2842void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002843printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002844{
2845 tprintf("\n");
2846 tcp_last = NULL;
2847}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002848
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002849#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002850
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002851int
2852mp_ioctl(int fd, int cmd, void *arg, int size)
2853{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002854 struct iovec iov[2];
2855 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002856
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002857 iov[0].iov_base = &cmd;
2858 iov[0].iov_len = sizeof cmd;
2859 if (arg) {
2860 ++n;
2861 iov[1].iov_base = arg;
2862 iov[1].iov_len = size;
2863 }
Roland McGrath553a6092002-12-16 20:40:39 +00002864
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002865 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002866}
2867
2868#endif